<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<meta name="theme-color" content="#222"><meta name="generator" content="Hexo 7.3.0">

  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32.ico">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16.ico">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">



<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" integrity="sha256-wiz7ZSCn/btzhjKDQBms9Hx4sSeUYsDrTLg7roPstac=" crossorigin="anonymous">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.1.1/animate.min.css" integrity="sha256-PR7ttpcvz8qrF57fur/yAx1qXMFJeJFiA6pSzWi0OIE=" crossorigin="anonymous">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/fancyapps-ui/5.0.28/fancybox/fancybox.css" integrity="sha256-6cQIC71/iBIYXFK+0RHAvwmjwWzkWd+r7v/BX3/vZDc=" crossorigin="anonymous">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/pace/1.2.4/themes/green/pace-theme-minimal.css">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/pace/1.2.4/pace.min.js" integrity="sha256-gqd7YTjg/BtfqWSwsJOvndl0Bxc8gFImLEkXQT8+qj0=" crossorigin="anonymous"></script>

<script class="next-config" data-name="main" type="application/json">{"hostname":"sumumm.github.io","root":"/","images":"/images","scheme":"Gemini","darkmode":false,"version":"8.19.2","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12},"copycode":{"enable":true,"style":"mac"},"fold":{"enable":true,"height":300},"bookmark":{"enable":false,"color":"#222","save":"auto"},"mediumzoom":false,"lazyload":true,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"stickytabs":false,"motion":{"enable":true,"async":true,"transition":{"menu_item":"fadeInDown","post_block":"fadeIn","post_header":"fadeInDown","post_body":"fadeInDown","coll_header":"fadeInLeft","sidebar":"fadeInUp"}},"i18n":{"placeholder":"搜索...","empty":"没有找到任何搜索结果：${query}","hits_time":"找到 ${hits} 个搜索结果（用时 ${time} 毫秒）","hits":"找到 ${hits} 个搜索结果"},"path":"/search.xml","localsearch":{"enable":true,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false}}</script><script src="/js/config.js"></script>

    <meta name="description" content="怎么使用设备树？若笔记中有错误或者不合适的地方，欢迎批评指正😃。">
<meta property="og:type" content="article">
<meta property="og:title" content="LV06-10-设备树-04-设备树的应用">
<meta property="og:url" content="https://sumumm.github.io/post/3df14f88.html">
<meta property="og:site_name" content="苏木">
<meta property="og:description" content="怎么使用设备树？若笔记中有错误或者不合适的地方，欢迎批评指正😃。">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/02IMX6ULL%E5%B9%B3%E5%8F%B0/LV06-%E9%A9%B1%E5%8A%A8%E5%BC%80%E5%8F%91/LV06-10-%E8%AE%BE%E5%A4%87%E6%A0%91-04-%E8%AE%BE%E5%A4%87%E6%A0%91%E7%9A%84%E5%BA%94%E7%94%A8/img/image-20250225164508489.png">
<meta property="og:image" content="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/02IMX6ULL%E5%B9%B3%E5%8F%B0/LV06-%E9%A9%B1%E5%8A%A8%E5%BC%80%E5%8F%91/LV06-10-%E8%AE%BE%E5%A4%87%E6%A0%91-04-%E8%AE%BE%E5%A4%87%E6%A0%91%E7%9A%84%E5%BA%94%E7%94%A8/img/image-20250309161117557.png">
<meta property="og:image" content="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/02IMX6ULL%E5%B9%B3%E5%8F%B0/LV06-%E9%A9%B1%E5%8A%A8%E5%BC%80%E5%8F%91/LV06-10-%E8%AE%BE%E5%A4%87%E6%A0%91-04-%E8%AE%BE%E5%A4%87%E6%A0%91%E7%9A%84%E5%BA%94%E7%94%A8/img/image-20250309161625812.png">
<meta property="og:image" content="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/02IMX6ULL%E5%B9%B3%E5%8F%B0/LV06-%E9%A9%B1%E5%8A%A8%E5%BC%80%E5%8F%91/LV06-10-%E8%AE%BE%E5%A4%87%E6%A0%91-04-%E8%AE%BE%E5%A4%87%E6%A0%91%E7%9A%84%E5%BA%94%E7%94%A8/img/image-20250309162949432.png">
<meta property="og:image" content="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/02IMX6ULL%E5%B9%B3%E5%8F%B0/LV06-%E9%A9%B1%E5%8A%A8%E5%BC%80%E5%8F%91/LV06-10-%E8%AE%BE%E5%A4%87%E6%A0%91-04-%E8%AE%BE%E5%A4%87%E6%A0%91%E7%9A%84%E5%BA%94%E7%94%A8/img/image-20250309164449464.png">
<meta property="og:image" content="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/02IMX6ULL%E5%B9%B3%E5%8F%B0/LV06-%E9%A9%B1%E5%8A%A8%E5%BC%80%E5%8F%91/LV06-10-%E8%AE%BE%E5%A4%87%E6%A0%91-04-%E8%AE%BE%E5%A4%87%E6%A0%91%E7%9A%84%E5%BA%94%E7%94%A8/img/image-20250119115206386.png">
<meta property="og:image" content="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/02IMX6ULL%E5%B9%B3%E5%8F%B0/LV06-%E9%A9%B1%E5%8A%A8%E5%BC%80%E5%8F%91/LV06-10-%E8%AE%BE%E5%A4%87%E6%A0%91-04-%E8%AE%BE%E5%A4%87%E6%A0%91%E7%9A%84%E5%BA%94%E7%94%A8/img/image-20250309193144637.png">
<meta property="og:image" content="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/02IMX6ULL%E5%B9%B3%E5%8F%B0/LV06-%E9%A9%B1%E5%8A%A8%E5%BC%80%E5%8F%91/LV06-10-%E8%AE%BE%E5%A4%87%E6%A0%91-04-%E8%AE%BE%E5%A4%87%E6%A0%91%E7%9A%84%E5%BA%94%E7%94%A8/img/image-20250309193337157.png">
<meta property="og:image" content="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/02IMX6ULL%E5%B9%B3%E5%8F%B0/LV06-%E9%A9%B1%E5%8A%A8%E5%BC%80%E5%8F%91/LV06-10-%E8%AE%BE%E5%A4%87%E6%A0%91-04-%E8%AE%BE%E5%A4%87%E6%A0%91%E7%9A%84%E5%BA%94%E7%94%A8/img/image-20250309195107101.png">
<meta property="og:image" content="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/02IMX6ULL%E5%B9%B3%E5%8F%B0/LV06-%E9%A9%B1%E5%8A%A8%E5%BC%80%E5%8F%91/LV06-10-%E8%AE%BE%E5%A4%87%E6%A0%91-04-%E8%AE%BE%E5%A4%87%E6%A0%91%E7%9A%84%E5%BA%94%E7%94%A8/img/image-20250309195026404.png">
<meta property="article:published_time" content="2025-03-16T23:45:54.000Z">
<meta property="article:modified_time" content="2025-06-13T16:25:57.055Z">
<meta property="article:author" content="苏木">
<meta property="article:tag" content="LV06-驱动开发">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/02IMX6ULL%E5%B9%B3%E5%8F%B0/LV06-%E9%A9%B1%E5%8A%A8%E5%BC%80%E5%8F%91/LV06-10-%E8%AE%BE%E5%A4%87%E6%A0%91-04-%E8%AE%BE%E5%A4%87%E6%A0%91%E7%9A%84%E5%BA%94%E7%94%A8/img/image-20250225164508489.png">


<link rel="canonical" href="https://sumumm.github.io/post/3df14f88.html">



<script class="next-config" data-name="page" type="application/json">{"sidebar":"","isHome":false,"isPost":true,"lang":"zh-CN","comments":"","permalink":"https://sumumm.github.io/post/3df14f88.html","path":"post/3df14f88.html","title":"LV06-10-设备树-04-设备树的应用"}</script>

<script class="next-config" data-name="calendar" type="application/json">""</script>
<title>LV06-10-设备树-04-设备树的应用 | 苏木</title>
  








    <script src="/js/browser_tools_disable.js"></script>

  <noscript>
    <link rel="stylesheet" href="/css/noscript.css">
  </noscript>
<!-- hexo injector head_end start --><link rel="stylesheet" href="https://unpkg.com/hexo-next-tags-plus@latest/lib/tag_plus.css" media="defer" onload="this.media='all'"><!-- hexo injector head_end end --></head>

<body itemscope itemtype="http://schema.org/WebPage" class="use-motion">
  <div class="headband"></div>

  <main class="main">
    <div class="column">
      <header class="header" itemscope itemtype="http://schema.org/WPHeader"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏" role="button">
        <span class="toggle-line"></span>
        <span class="toggle-line"></span>
        <span class="toggle-line"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <i class="logo-line"></i>
      <p class="site-title">苏木</p>
      <i class="logo-line"></i>
    </a>
      <p class="site-subtitle" itemprop="description">我的学习之路</p>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger" aria-label="搜索" role="button">
        <i class="fa fa-search fa-fw fa-lg"></i>
    </div>
  </div>
</div>



<nav class="site-nav">
  <ul class="main-menu menu"><li class="menu-item menu-item-home"><a href="/" rel="section"><i class="fa fa-home fa-fw"></i>苏木的家</a></li><li class="menu-item menu-item-categories"><a href="/categories/" rel="section"><i class="fa fa-th fa-fw"></i>分类页<span class="badge">42</span></a></li><li class="menu-item menu-item-archives"><a href="/archives/" rel="section"><i class="fa fa-archive fa-fw"></i>归档页<span class="badge">673</span></a></li><li class="menu-item menu-item-flink"><a href="/flink/" rel="section"><i class="fa fa-link fa-fw"></i>友人帐</a></li><li class="menu-item menu-item-about"><a href="/about/" rel="section"><i class="fa fa-user fa-fw"></i>关于我</a></li>
      <li class="menu-item menu-item-search">
        <a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>搜索
        </a>
      </li>
  </ul>
</nav>



  <div class="search-pop-overlay">
    <div class="popup search-popup"><div class="search-header">
  <span class="search-icon">
    <i class="fa fa-search"></i>
  </span>
  <div class="search-input-container">
    <input autocomplete="off" autocapitalize="off" maxlength="80"
           placeholder="搜索..." spellcheck="false"
           type="search" class="search-input">
  </div>
  <span class="popup-btn-close" role="button">
    <i class="fa fa-times-circle"></i>
  </span>
</div>
<div class="search-result-container no-result">
  <div class="search-result-icon">
    <i class="fa fa-spinner fa-pulse fa-5x"></i>
  </div>
</div>

    </div>
  </div>

</header>
        
  
  <aside class="sidebar">

    <div class="sidebar-inner sidebar-nav-active sidebar-toc-active">
      <ul class="sidebar-nav">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <div class="sidebar-panel-container">
        <!--noindex-->
        <div class="post-toc-wrap sidebar-panel">
            <div class="post-toc animated"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%B8%80%E3%80%81%E5%86%85%E6%A0%B8%E6%93%8D%E4%BD%9C%E8%AE%BE%E5%A4%87%E6%A0%91%E7%9A%84%E5%87%BD%E6%95%B0"><span class="nav-text">一、内核操作设备树的函数</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#1-%E5%86%85%E6%A0%B8%E4%B8%AD%E8%AE%BE%E5%A4%87%E6%A0%91%E7%9B%B8%E5%85%B3%E7%9A%84%E5%A4%B4%E6%96%87%E4%BB%B6%E4%BB%8B%E7%BB%8D"><span class="nav-text">1. 内核中设备树相关的头文件介绍  </span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#1-1-%E5%A4%84%E7%90%86-DTB"><span class="nav-text">1.1 处理 DTB  </span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#1-2-%E5%A4%84%E7%90%86-device-node"><span class="nav-text">1.2 处理 device_node  </span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#1-3-%E5%A4%84%E7%90%86-platform-device"><span class="nav-text">1.3 处理 platform_device  </span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#2-OF%E5%87%BD%E6%95%B0"><span class="nav-text">2. OF函数</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#2-1-%E8%8E%B7%E5%8F%96%E8%AE%BE%E5%A4%87%E6%A0%91%E8%8A%82%E7%82%B9"><span class="nav-text">2.1 获取设备树节点</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#2-1-1-of-find-node-by-name"><span class="nav-text">2.1.1 of_find_node_by_name()</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#2-1-2-of-find-node-by-path"><span class="nav-text">2.1.2 of_find_node_by_path()</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#2-1-3-of-find-node-by-type"><span class="nav-text">2.1.3 of_find_node_by_type()</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#2-1-4-of-find-compatible-node"><span class="nav-text">2.1.4 of_find_compatible_node()</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#2-1-5-of-find-node-by-phandle"><span class="nav-text">2.1.5 of_find_node_by_phandle()</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#2-1-6-of-find-matching-node-and-match"><span class="nav-text">2.1.6 of_find_matching_node_and_match()</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-2-%E6%9F%A5%E6%89%BE%E7%88%B6%E5%AD%90%E8%8A%82%E7%82%B9"><span class="nav-text">2.2 查找父子节点</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#2-2-1-of-get-parent"><span class="nav-text">2.2.1 of_get_parent() </span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#2-2-2-of-get-next-parent"><span class="nav-text">2.2.2 of_get_next_parent()</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#2-2-3-of-get-next-child"><span class="nav-text">2.2.3 of_get_next_child()</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#2-2-4-of-get-next-available-child"><span class="nav-text">2.2.4 of_get_next_available_child()</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#2-2-5-of-get-child-by-name"><span class="nav-text">2.2.5 of_get_child_by_name()</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-3-%E8%8E%B7%E5%8F%96%E5%B1%9E%E6%80%A7"><span class="nav-text">2.3 获取属性</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#2-3-1-of-find-property"><span class="nav-text">2.3.1 of_find_property()</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#2-3-2-of-property-count-elems-of-size"><span class="nav-text">2.3.2 of_property_count_elems_of_size()</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#2-3-3-%E8%AF%BB%E6%95%B0%E7%BB%84-u8-u16-u32-u64"><span class="nav-text">2.3.3 读数组 u8&#x2F;u16&#x2F;u32&#x2F;u64</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#2-3-4-%E8%AF%BB%E6%95%B4%E6%95%B0-u8-u16-u32-u64"><span class="nav-text">2.3.4 读整数 u8&#x2F;u16&#x2F;u32&#x2F;u64</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#2-3-5-%E8%AF%BB%E6%9F%90%E4%B8%AA%E6%95%B4%E6%95%B0-u32"><span class="nav-text">2.3.5 读某个整数 u32</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#2-3-6-%E8%AF%BB%E6%9F%90%E4%B8%AA%E6%95%B4%E6%95%B0-u64"><span class="nav-text">2.3.6 读某个整数 u64</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#2-3-7-%E8%AF%BB%E5%AD%97%E7%AC%A6%E4%B8%B2"><span class="nav-text">2.3.7 读字符串</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#2-3-8-%E8%AF%BB%E8%8E%B7%E5%8F%96-address-cells"><span class="nav-text">2.3.8 读获取#address-cells  </span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#2-3-9-%E8%AF%BB%E5%8F%96-size-cells"><span class="nav-text">2.3.9 读取#size-cells  </span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-4-%E5%85%B6%E4%BB%96%E5%87%BD%E6%95%B0"><span class="nav-text">2.4 其他函数</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#2-4-1-of-device-is-compatible"><span class="nav-text">2.4.1 of_device_is_compatible()  </span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#2-4-2-of-get-address"><span class="nav-text">2.4.2 of_get_address() </span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#2-4-3-of-translate-address"><span class="nav-text">2.4.3 of_translate_address()</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#2-4-4-of-address-to-resource"><span class="nav-text">2.4.4 of_address_to_resource()</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#2-4-5-of-iomap"><span class="nav-text">2.4.5 of_iomap()</span></a></li></ol></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#3-platform-device-%E7%9B%B8%E5%85%B3%E7%9A%84%E5%87%BD%E6%95%B0"><span class="nav-text">3. platform_device 相关的函数  </span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#3-1-of-find-device-by-node"><span class="nav-text">3.1 of_find_device_by_node()</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#3-2-platform-get-resource"><span class="nav-text">3.2 platform_get_resource()</span></a></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%BA%8C%E3%80%81of%E5%87%BD%E6%95%B0%E4%BD%BF%E7%94%A8%E5%AE%9E%E4%BE%8B"><span class="nav-text">二、of函数使用实例</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#1-%E8%AE%BE%E5%A4%87%E6%A0%91%E8%8A%82%E7%82%B9%E5%87%86%E5%A4%87"><span class="nav-text">1. 设备树节点准备</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#2-of%E8%8E%B7%E5%8F%96%E8%AE%BE%E5%A4%87%E8%8A%82%E7%82%B9%E5%AE%9E%E4%BE%8B"><span class="nav-text">2. of获取设备节点实例</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#2-1-demo%E6%BA%90%E7%A0%81"><span class="nav-text">2.1 demo源码</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-2-%E5%BC%80%E5%8F%91%E6%9D%BF%E6%B5%8B%E8%AF%95"><span class="nav-text">2.2 开发板测试</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#3-of%E8%8E%B7%E5%8F%96%E8%AE%BE%E5%A4%87%E8%8A%82%E7%82%B9%E5%B1%9E%E6%80%A7%E5%AE%9E%E4%BE%8B"><span class="nav-text">3. of获取设备节点属性实例</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#3-1-demo%E6%BA%90%E7%A0%81"><span class="nav-text">3.1 demo源码</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#3-2-%E5%BC%80%E5%8F%91%E6%9D%BF%E6%B5%8B%E8%AF%95"><span class="nav-text">3.2 开发板测试</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#4-led%E5%AE%9E%E4%BE%8B"><span class="nav-text">4. led实例</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%B8%89%E3%80%81%E8%AE%BE%E5%A4%87%E6%A0%91%E4%B8%8B%E7%9A%84%E5%B9%B3%E5%8F%B0%E8%AE%BE%E5%A4%87%E9%A9%B1%E5%8A%A8"><span class="nav-text">三、设备树下的平台设备驱动</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#1-platform-device-%E5%A6%82%E4%BD%95%E4%B8%8E-platform-driver-%E9%85%8D%E5%AF%B9"><span class="nav-text">1. platform_device 如何与 platform_driver 配对  </span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#1-1-%E5%BC%BA%E5%88%B6%E9%80%89%E6%8B%A9%E9%A9%B1%E5%8A%A8"><span class="nav-text">1.1 强制选择驱动</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#1-2-%E8%AE%BE%E5%A4%87%E6%A0%91%E5%8C%B9%E9%85%8D"><span class="nav-text">1.2 设备树匹配</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#1-3-id%E5%8C%B9%E9%85%8D"><span class="nav-text">1.3 id匹配</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#1-4-name%E5%8C%B9%E9%85%8D"><span class="nav-text">1.4 name匹配</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#1-5-%E6%80%BB%E7%BB%93"><span class="nav-text">1.5 总结</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#2-%E8%AE%BE%E5%A4%87%E6%A0%91%E5%8C%B9%E9%85%8D%E5%AE%9E%E4%BE%8B"><span class="nav-text">2. 设备树匹配实例</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#2-1-%E9%9C%80%E8%A6%81%E5%93%AA%E4%BA%9B%E6%9D%A1%E4%BB%B6%EF%BC%9F"><span class="nav-text">2.1 需要哪些条件？</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-2-%E5%9F%BA%E6%9C%AC%E6%A1%86%E6%9E%B6"><span class="nav-text">2.2 基本框架</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-3-demo%E6%BA%90%E7%A0%81"><span class="nav-text">2.3 demo源码</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#2-4-%E8%B0%83%E8%AF%95%E6%8A%80%E5%B7%A7"><span class="nav-text">2.4 调试技巧</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#3-%E4%BB%8Eplatform-device%E8%8E%B7%E5%8F%96%E8%8A%82%E7%82%B9%E4%BF%A1%E6%81%AF"><span class="nav-text">3. 从platform_device获取节点信息</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#3-1-%E6%80%8E%E4%B9%88%E6%8B%BF%E5%88%B0%E8%8A%82%E7%82%B9%EF%BC%9F"><span class="nav-text">3.1 怎么拿到节点？</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#3-2-demo%E6%BA%90%E7%A0%81"><span class="nav-text">3.2 demo源码</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#3-3-%E5%BC%80%E5%8F%91%E6%9D%BF%E6%B5%8B%E8%AF%95"><span class="nav-text">3.3 开发板测试</span></a></li></ol></li></ol></li></ol></div>
        </div>
        <!--/noindex-->

        <div class="site-overview-wrap sidebar-panel">
          <div class="site-author animated" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="苏木"
      src="/images/avatar.jpg">
  <p class="site-author-name" itemprop="name">苏木</p>
  <div class="site-description" itemprop="description">莫道桑榆晚，为霞尚满天</div>
</div>
<div class="site-state-wrap animated">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
        <a href="/archives/">
          <span class="site-state-item-count">673</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
          <a href="/categories/">
        <span class="site-state-item-count">42</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
        <span class="site-state-item-count">43</span>
        <span class="site-state-item-name">标签</span>
      </div>
  </nav>
</div>
  <div class="links-of-author animated">
      <span class="links-of-author-item">
        <a href="https://github.com/sumumm" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;sumumm" rel="noopener me" target="_blank"><i class="fab fa-github fa-fw"></i>GitHub</a>
      </span>
  </div>

        </div>
      </div>
    </div>

    
  </aside>


    </div>

    <div class="main-inner post posts-expand">


  


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://sumumm.github.io/post/3df14f88.html">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.jpg">
      <meta itemprop="name" content="苏木">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="苏木">
      <meta itemprop="description" content="莫道桑榆晚，为霞尚满天">
    </span>

    <span hidden itemprop="post" itemscope itemtype="http://schema.org/CreativeWork">
      <meta itemprop="name" content="LV06-10-设备树-04-设备树的应用 | 苏木">
      <meta itemprop="description" content="">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          LV06-10-设备树-04-设备树的应用
        </h1>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>

      <time title="创建时间：2025-03-17 07:45:54" itemprop="dateCreated datePublished" datetime="2025-03-17T07:45:54+08:00">2025-03-17</time>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">分类于</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/" itemprop="url" rel="index"><span itemprop="name">嵌入式开发</span></a>
        </span>
          ，
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/02IMX6ULL%E5%B9%B3%E5%8F%B0/" itemprop="url" rel="index"><span itemprop="name">02IMX6ULL平台</span></a>
        </span>
          ，
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/02IMX6ULL%E5%B9%B3%E5%8F%B0/LV06-%E9%A9%B1%E5%8A%A8%E5%BC%80%E5%8F%91/" itemprop="url" rel="index"><span itemprop="name">LV06-驱动开发</span></a>
        </span>
    </span>

  
    <span class="post-meta-break"></span>
    <span class="post-meta-item" title="本文字数">
      <span class="post-meta-item-icon">
        <i class="far fa-file-word"></i>
      </span>
      <span class="post-meta-item-text">本文字数：</span>
      <span>11k</span>
    </span>
    <span class="post-meta-item" title="阅读时长">
      <span class="post-meta-item-icon">
        <i class="far fa-clock"></i>
      </span>
      <span class="post-meta-item-text">阅读时长 &asymp;</span>
      <span>39 分钟</span>
    </span>
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody"><p>怎么使用设备树？若笔记中有错误或者不合适的地方，欢迎批评指正😃。</p>
<span id="more"></span>

<!-- Photo: https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/02IMX6ULL%E5%B9%B3%E5%8F%B0/LV06-%E9%A9%B1%E5%8A%A8%E5%BC%80%E5%8F%91/LV06-10-%E8%AE%BE%E5%A4%87%E6%A0%91-04-%E8%AE%BE%E5%A4%87%E6%A0%91%E7%9A%84%E5%BA%94%E7%94%A8/img/ -->

<details class="folding-tag" blue><summary> 点击查看使用工具及版本 </summary>
              <div class='content'>
              <table>    <tr>        <td align="center" rowspan="5">PC端开发环境</td>        <td align="center" width=150px>Windows</td>        <td align="left">Windows11</td>    </tr>    <tr>        <td align="center">Ubuntu</td>        <td align="left">Ubuntu20.04.2的64位版本</td>      </tr>    <tr>        <td align="center">VMware® Workstation 17 Pro</td>        <td align="left">17.6.0 build-24238078</td>      </tr>    <tr>        <td align="center">终端软件</td>        <td align="left">MobaXterm(Professional Edition v23.0 Build 5042 (license))</td>    </tr>    <tr>        <td align="center">Win32DiskImager</td>        <td align="left">Win32DiskImager v1.0</td>      </tr>    <tr>        <td align="center" rowspan="3">Linux开发板环境</td>        <td align="center">Linux开发板</td>        <td align="left">正点原子 i.MX6ULL Linux 阿尔法开发板</td>      </tr>    <tr>        <td align="center">uboot</td>        <td align="left">NXP官方提供的uboot，使用的uboot版本为U-Boot 2019.04</td>      </tr>    <tr>        <td align="center">linux内核</td>        <td align="left">linux-4.19.71(NXP官方提供)</td>      </tr></table>
              </div>
            </details>

<details class="folding-tag" blue><summary> 点击查看本文参考资料 </summary>
              <div class='content'>
              <table>    <tr>        <td align="center">分类</td>        <td align="center">网址</td>        <td align="center">说明</td>    </tr>    <tr>        <td align="center" rowspan="5">官方网站</td>        <td align="left"><a href="https://www.arm.com/" target="_blank">https://www.arm.com/</a></td>        <td align="left">ARM官方网站，在这里我们可以找到Cotex-Mx以及ARMVx的一些文档</td>    </tr>    <tr>        <td align="left"><a href="https://www.nxp.com.cn/" target="_blank">https://www.nxp.com.cn/ </a></td>        <td align="left">NXP官方网站</td>    </tr>    <tr>        <td align="left"><a href="https://www.nxpic.org.cn/" target="_blank">https://www.nxpic.org.cn/</a></td><td align="left">NXP 官方社区</td>    </tr>    <tr>        <td align="left"><a href="https://u-boot.readthedocs.io/en/latest/" target="_blank">https://u-boot.readthedocs.io/en/latest/</a></td><td align="left">u-boot官网</td>    </tr>    <tr>        <td align="left"><a href="https://www.kernel.org/" target="_blank">https://www.kernel.org/</a></td><td align="left">linux内核官网</td>    </tr></table>
              </div>
            </details>

<details class="folding-tag" blue><summary> 点击查看相关文件下载 </summary>
              <div class='content'>
              <table>    <tr>        <td align="center">分类</td>        <td align="center">网址</td>        <td align="center">说明</td>    </tr>    <tr>        <td align="center" rowspan="3">NXP</td>        <td align="left"><a href="https://github.com/nxp-imx" target="_blank">https://github.com/nxp-imx</a></td>        <td align="left">NXP imx开发资源GitHub组织，里边会有u-boot和linux内核的仓库</td>    </tr>    <tr>        <td align="left"><a href="https://github.com/nxp-imx/linux-imx/releases/tag/v4.19.71" target="_blank">nxp-imx/linux-imx/releases/tag/v4.19.71</a></td>        <td align="left">NXP linux内核仓库tags中的v4.19.71</td>    </tr>    <tr>        <td align="left"><a href="https://github.com/nxp-imx/uboot-imx/releases/tag/rel_imx_4.19.35_1.1.0" target="_blank">nxp-imx/uboot-imx/releases/tag/rel_imx_4.19.35_1.1.0</a></td>        <td align="left">NXP u-boot仓库tags中的rel_imx_4.19.35_1.1.0</td>    </tr>    <tr>        <td align="center" rowspan="2">I.MX6ULL</td>        <td align="left"><a href="https://www.nxp.com.cn/docs/en/data-sheet/IMX6ULLIEC.pdf" target="_blank">i.MX 6ULL Applications Processors for Industrial Products</a></td>        <td align="left">I.MX6ULL 芯片手册（datasheet，可以在线查看）</td>    </tr>    <tr>        <td align="left"><a href="https://www.nxp.com.cn/webapp/Download?colCode=IMX6ULLRM&lang_cd=zh" target="_blank">i.MX 6ULL Applications ProcessorReference Manual</a></td>        <td align="left">I.MX6ULL 参考手册（下载后才能查看，需要登录NXP官网）</td>    </tr>    <tr>        <td align="center" rowspan="3">Source Code</td>        <td align="left"><a href="https://elixir.bootlin.com/linux/latest/source" target="_blank">https://elixir.bootlin.com/linux/latest/source</a></td>        <td align="left">linux kernel源码</td>    </tr>    <tr>        <td align="left"><a href="https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/?h=v4.19.71&id=e7d2672c66e4d3675570369bf20856296da312c4" target="_blank">kernel/git/stable/linux.git - Linux kernel stable tree</a></td>        <td align="left">linux kernel源码(官网,tag 4.19.71)</td>    </tr>    <tr>        <td align="left"><a href="https://elixir.bootlin.com/u-boot/latest/source" target="_blank">https://elixir.bootlin.com/u-boot/latest/source</a></td>        <td align="left">uboot源码</td>    </tr></table>
              </div>
            </details>

<h1 id="一、内核操作设备树的函数"><a href="#一、内核操作设备树的函数" class="headerlink" title="一、内核操作设备树的函数"></a><font size=3>一、内核操作设备树的函数</font></h1><p>内核源码中 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/include/linux">linux - include&#x2F;linux</a> 目录下有很多 of 开头的头文件， of 表示“open firmware”即开放固件。  </p>
<img data-src="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/02IMX6ULL%E5%B9%B3%E5%8F%B0/LV06-%E9%A9%B1%E5%8A%A8%E5%BC%80%E5%8F%91/LV06-10-%E8%AE%BE%E5%A4%87%E6%A0%91-04-%E8%AE%BE%E5%A4%87%E6%A0%91%E7%9A%84%E5%BA%94%E7%94%A8/img/image-20250225164508489.png" alt="image-20250225164508489"  />

<h2 id="1-内核中设备树相关的头文件介绍"><a href="#1-内核中设备树相关的头文件介绍" class="headerlink" title="1. 内核中设备树相关的头文件介绍  "></a><font size=3>1. 内核中设备树相关的头文件介绍  </font></h2><p>前面我们已经了解过了，设备树的处理过程是： dtb -&gt; device_node -&gt; platform_device。  </p>
<h3 id="1-1-处理-DTB"><a href="#1-1-处理-DTB" class="headerlink" title="1.1 处理 DTB  "></a><font size=3>1.1 处理 DTB  </font></h3><ul>
<li><a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/include/linux/of_fdt.h">of_fdt.h - include&#x2F;linux&#x2F;of_fdt.h</a>：dtb 文件的相关操作函数, 我们一般用不到,  因为 dtb 文件在内核中已经被转换为 device_node 树(它更易于使用)</li>
</ul>
<h3 id="1-2-处理-device-node"><a href="#1-2-处理-device-node" class="headerlink" title="1.2 处理 device_node  "></a><font size=3>1.2 处理 device_node  </font></h3><ul>
<li><p><a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/include/linux/of.h">of.h - include&#x2F;linux&#x2F;of.h</a> ：提供设备树的一般处理函数，比如 of_property_read_u32(读取某个属性的 u32 值)，of_get_child_count(获取某个 device_node 的子节点数)</p>
</li>
<li><p><a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/include/linux/of_address.h">of_address.h - include&#x2F;linux&#x2F;of_address.h</a>：地址相关的函数，比如 of_get_address(获得 reg 属性中的 addr, size 值) ， of_match_device (从 matches 数组中取出与当前设备最匹配的一项)</p>
</li>
<li><p><a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/include/linux/of_dma.h">of_dma.h - include&#x2F;linux&#x2F;of_dma.h</a>：设备树中 DMA 相关属性的函数</p>
</li>
<li><p><a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/include/linux/of_gpio.h">of_gpio.h - include&#x2F;linux&#x2F;of_gpio.h</a>：GPIO 相关的函数</p>
</li>
<li><p><a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/include/linux/of_graph.h">of_graph.h - include&#x2F;linux&#x2F;of_graph.h</a>：GPU 相关驱动中用到的函数, 从设备树中获得 GPU 信息</p>
</li>
<li><p><a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/include/linux/of_iommu.h">of_iommu.h - include&#x2F;linux&#x2F;of_iommu.h</a>：很少用到</p>
</li>
<li><p><a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/include/linux/of_irq.h">of_irq.h - include&#x2F;linux&#x2F;of_irq.h</a>：中断相关的函数</p>
</li>
<li><p><a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/include/linux/of_mdio.h">of_mdio.h - include&#x2F;linux&#x2F;of_mdio.h</a>：MDIO (Ethernet PHY) API</p>
</li>
<li><p><a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/include/linux/of_net.h">of_net.h - include&#x2F;linux&#x2F;of_net.h</a>：OF helpers for network devices.</p>
</li>
<li><p><a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/include/linux/of_pci.h">of_pci.h - include&#x2F;linux&#x2F;of_pci.h</a>：PCI 相关函数</p>
</li>
<li><p><a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/include/linux/of_pdt.h">of_pdt.h - include&#x2F;linux&#x2F;of_pdt.h</a>：很少用到</p>
</li>
<li><p><a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/include/linux/of_reserved_mem.h">of_reserved_mem.h - include&#x2F;linux&#x2F;of_reserved_mem.h</a>：reserved_mem 的相关函数</p>
</li>
</ul>
<h3 id="1-3-处理-platform-device"><a href="#1-3-处理-platform-device" class="headerlink" title="1.3 处理 platform_device  "></a><font size=3>1.3 处理 platform_device  </font></h3><ul>
<li><a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/include/linux/of_platform.h">of_platform.h - include&#x2F;linux&#x2F;of_platform.h</a>：把 device_node 转换为 platform_device 时用到的函数。</li>
</ul>
<p>比如 of_device_alloc(根据 device_node 分配设置 platform_device)，of_find_device_by_node (根据 device_node 查找到 platform_device)，of_platform_bus_probe (处理 device_node 及它的子节点)</p>
<ul>
<li><a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/include/linux/of_device.h">of_device.h - include&#x2F;linux&#x2F;of_device.h</a>：设备相关的函数, 比如 of_match_device</li>
</ul>
<h2 id="2-OF函数"><a href="#2-OF函数" class="headerlink" title="2. OF函数"></a><font size=3>2. OF函数</font></h2><p>设备树描述了设备的详细信息，这些信息包括数字类型的、字符串类型的、数组类型的，我们在编写驱动的时候需要获取到这些信息。比如设备树使用 reg 属性描述了某个外设的寄存器地址为 0X02005482，长度为 0X400，我们在编写驱动的时候需要获取到 reg 属性的0X02005482 和 0X400 这两个值，然后初始化外设。 </p>
<p>Linux 内核给我们提供了一系列的函数来获取设备树中的节点或者属性信息，这一系列的函数都有一个统一的前缀“of_”，所以在很多资料里面也被叫做 <strong>OF 函数</strong>。这些 OF 函数原型一般都定义在 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/include/linux/of.h">of.h - include&#x2F;linux&#x2F;of.h</a>  文件中。在使用的时候要包含<code>#include &lt;linux/of.h&gt;</code>文件。</p>
<p>在内核中以 device_node 结构体来对设备树进行描述， 所以 of 操作函数实际上就是获取device_node 结构体 。</p>
<h3 id="2-1-获取设备树节点"><a href="#2-1-获取设备树节点" class="headerlink" title="2.1 获取设备树节点"></a><font size=3>2.1 获取设备树节点</font></h3><h4 id="2-1-1-of-find-node-by-name"><a href="#2-1-1-of-find-node-by-name" class="headerlink" title="2.1.1 of_find_node_by_name()"></a><font size=3>2.1.1 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/drivers/of/base.c#L939">of_find_node_by_name()</a></font></h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">struct</span> device_node *<span class="title function_">of_find_node_by_name</span><span class="params">(<span class="keyword">struct</span> device_node *from,</span></span><br><span class="line"><span class="params">	<span class="type">const</span> <span class="type">char</span> *name)</span></span><br><span class="line">&#123;</span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">device_node</span> *<span class="title">np</span>;</span></span><br><span class="line">	<span class="type">unsigned</span> <span class="type">long</span> flags;</span><br><span class="line"></span><br><span class="line">	raw_spin_lock_irqsave(&amp;devtree_lock, flags);</span><br><span class="line">	for_each_of_allnodes_from(from, np)</span><br><span class="line">		<span class="keyword">if</span> (np-&gt;name &amp;&amp; (of_node_cmp(np-&gt;name, name) == <span class="number">0</span>)</span><br><span class="line">		    &amp;&amp; of_node_get(np))</span><br><span class="line">			<span class="keyword">break</span>;</span><br><span class="line">	of_node_put(from);</span><br><span class="line">	raw_spin_unlock_irqrestore(&amp;devtree_lock, flags);</span><br><span class="line">	<span class="keyword">return</span> np;</span><br><span class="line">&#125;</span><br><span class="line">EXPORT_SYMBOL(of_find_node_by_name);</span><br></pre></td></tr></table></figure>

<p>该函数通过指定的节点名称在设备树中进行查找， 返回匹配的节点的 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/include/linux/of.h#L51">struct device_node</a> 指针。但是在设备树的官方规范中不建议使用“ name”属性，所以这函数也不建议使用。    </p>
<p><strong>参数说明：</strong></p>
<ul>
<li>from： 指定起始节点， 表示从哪个节点开始查找。 如果 from 参数为 NULL， 则从设备树的根节点开始查找。</li>
<li>name： 要查找的节点名称。</li>
</ul>
<p><strong>返回值：</strong>如果找到匹配的节点， 则返回对应的 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/include/linux/of.h#L51">struct device_node</a> 指针。如果未找到匹配的节点， 则返回 NULL。  </p>
<h4 id="2-1-2-of-find-node-by-path"><a href="#2-1-2-of-find-node-by-path" class="headerlink" title="2.1.2 of_find_node_by_path()"></a><font size=3>2.1.2 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/include/linux/of.h#L288">of_find_node_by_path()</a></font></h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">static</span> <span class="keyword">inline</span> <span class="keyword">struct</span> device_node *<span class="title function_">of_find_node_by_path</span><span class="params">(<span class="type">const</span> <span class="type">char</span> *path)</span></span><br><span class="line">&#123;</span><br><span class="line">	<span class="keyword">return</span> of_find_node_opts_by_path(path, <span class="literal">NULL</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>该函数通过节点路径在设备树中进行查找。 路径是设备树节点从根节点到目标节点的完整路径。 可以通过指定正确的路径来准确地访问设备树中的特定节点。使用该函数时， 可以直接传递节点的完整路径作为 path 参数， 函数会在设备树中查找匹配的节点。 这对于已知节点路径的情况非常有用。    </p>
<p><strong>参数说明：</strong></p>
<ul>
<li>path： 节点的路径， 以斜杠分隔的字符串表示。 路径格式为设备树节点的绝对路径， 例如 &#x2F; topeet&#x2F;myLed。</li>
</ul>
<p><strong>返回值：</strong>如果找到匹配的节点， 则返回对应的 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/include/linux/of.h#L51">struct device_node</a> 指针。如果未找到匹配的节点， 则返回 NULL。  </p>
<h4 id="2-1-3-of-find-node-by-type"><a href="#2-1-3-of-find-node-by-type" class="headerlink" title="2.1.3 of_find_node_by_type()"></a><font size=3>2.1.3 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/drivers/of/base.c#L967">of_find_node_by_type()</a></font></h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">struct</span> device_node *<span class="title function_">of_find_node_by_type</span><span class="params">(<span class="keyword">struct</span> device_node *from,</span></span><br><span class="line"><span class="params">	<span class="type">const</span> <span class="type">char</span> *type)</span></span><br><span class="line">&#123;</span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">device_node</span> *<span class="title">np</span>;</span></span><br><span class="line">	<span class="type">unsigned</span> <span class="type">long</span> flags;</span><br><span class="line"></span><br><span class="line">	raw_spin_lock_irqsave(&amp;devtree_lock, flags);</span><br><span class="line">	for_each_of_allnodes_from(from, np)</span><br><span class="line">		<span class="keyword">if</span> (np-&gt;type &amp;&amp; (of_node_cmp(np-&gt;type, type) == <span class="number">0</span>)</span><br><span class="line">		    &amp;&amp; of_node_get(np))</span><br><span class="line">			<span class="keyword">break</span>;</span><br><span class="line">	of_node_put(from);</span><br><span class="line">	raw_spin_unlock_irqrestore(&amp;devtree_lock, flags);</span><br><span class="line">	<span class="keyword">return</span> np;</span><br><span class="line">&#125;</span><br><span class="line">EXPORT_SYMBOL(of_find_node_by_type);</span><br></pre></td></tr></table></figure>

<p>该函数根据类型找到节点，节点如果定义了 device_type 属性，那我们可以根据类型找到它。但是在设备树的官方规范中不建议使用“ device_type”属性，所以这函数也不建议使用。        </p>
<p><strong>参数说明：</strong></p>
<ul>
<li>from： 指定起始节点， 表示从哪个节点开始查找。 如果 from 参数为 NULL， 则从设备树的根节点开始查找。</li>
<li>type： 要查找的节点的 device_type 属性。</li>
</ul>
<p><strong>返回值：</strong>如果找到匹配的节点， 则返回对应的 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/include/linux/of.h#L51">struct device_node</a> 指针。如果未找到匹配的节点， 则返回 NULL。  </p>
<h4 id="2-1-4-of-find-compatible-node"><a href="#2-1-4-of-find-compatible-node" class="headerlink" title="2.1.4 of_find_compatible_node()"></a><font size=3>2.1.4 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/drivers/of/base.c#L996">of_find_compatible_node()</a></font></h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">struct</span> device_node *<span class="title function_">of_find_compatible_node</span><span class="params">(<span class="keyword">struct</span> device_node *from,</span></span><br><span class="line"><span class="params">	<span class="type">const</span> <span class="type">char</span> *type, <span class="type">const</span> <span class="type">char</span> *compatible)</span></span><br><span class="line">&#123;</span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">device_node</span> *<span class="title">np</span>;</span></span><br><span class="line">	<span class="type">unsigned</span> <span class="type">long</span> flags;</span><br><span class="line"></span><br><span class="line">	raw_spin_lock_irqsave(&amp;devtree_lock, flags);</span><br><span class="line">	for_each_of_allnodes_from(from, np)</span><br><span class="line">		<span class="keyword">if</span> (__of_device_is_compatible(np, compatible, type, <span class="literal">NULL</span>) &amp;&amp;</span><br><span class="line">		    of_node_get(np))</span><br><span class="line">			<span class="keyword">break</span>;</span><br><span class="line">	of_node_put(from);</span><br><span class="line">	raw_spin_unlock_irqrestore(&amp;devtree_lock, flags);</span><br><span class="line">	<span class="keyword">return</span> np;</span><br><span class="line">&#125;</span><br><span class="line">EXPORT_SYMBOL(of_find_compatible_node);</span><br></pre></td></tr></table></figure>

<p>该函数根据 compatible 找到节点，节点如果定义了 compatible 属性，那我们可以根据 compatible 属性找到它。  </p>
<p><strong>参数说明：</strong></p>
<ul>
<li>from： 指定起始节点， 表示从哪个节点开始查找。 如果 from 参数为 NULL， 则从设备树的根节点开始查找。</li>
<li>type： 要匹配的设备类型字符串，用来指定 device_type 属性的值，可以传入 NULL，表示忽略掉 device_type 属性。</li>
<li>compatible： 要匹配的兼容性字符串， 通常是设备树节点的 compatible 属性中的值。</li>
</ul>
<p><strong>返回值：</strong>如果找到匹配的节点， 则返回对应的 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/include/linux/of.h#L51">struct device_node</a> 指针。如果未找到匹配的节点， 则返回 NULL。  </p>
<p>使用 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/drivers/of/base.c#L996">of_find_compatible_node()</a> 函数时， 可以指定起始节点和需要匹配的设备类型字符串以及兼容性字符串。 函数会从起始节点开始遍历设备树， 查找与指定兼容性字符串匹配的节点，并返回匹配节点的指针。  </p>
<h4 id="2-1-5-of-find-node-by-phandle"><a href="#2-1-5-of-find-node-by-phandle" class="headerlink" title="2.1.5 of_find_node_by_phandle()"></a><font size=3>2.1.5 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/drivers/of/base.c#L1170">of_find_node_by_phandle()</a></font></h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">struct</span> device_node *<span class="title function_">of_find_node_by_phandle</span><span class="params">(phandle handle)</span></span><br><span class="line">&#123;</span><br><span class="line">	<span class="comment">//......</span></span><br><span class="line">&#125;</span><br><span class="line">EXPORT_SYMBOL(of_find_node_by_phandle);</span><br></pre></td></tr></table></figure>

<p>该函数根据 phandle 找到节点。 dts 文件被编译为 dtb 文件时，每一个节点都有一个数字 ID，这些数字 ID 彼此不同。可以使用数字 ID 来找到 device_node。这些数字 ID 就是 phandle。  </p>
<p><strong>参数说明：</strong></p>
<ul>
<li>phandle： 要查找节点的数字id。</li>
</ul>
<p><strong>返回值：</strong>如果找到匹配的节点， 则返回对应的 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/include/linux/of.h#L51">struct device_node</a> 指针。如果未找到匹配的节点， 则返回 NULL。  </p>
<h4 id="2-1-6-of-find-matching-node-and-match"><a href="#2-1-6-of-find-matching-node-and-match" class="headerlink" title="2.1.6 of_find_matching_node_and_match()"></a><font size=3>2.1.6 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/drivers/of/base.c#L1104">of_find_matching_node_and_match()</a></font></h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">struct</span> device_node *<span class="title function_">of_find_matching_node_and_match</span><span class="params">(<span class="keyword">struct</span> device_node *from,</span></span><br><span class="line"><span class="params">					<span class="type">const</span> <span class="keyword">struct</span> of_device_id *matches,</span></span><br><span class="line"><span class="params">					<span class="type">const</span> <span class="keyword">struct</span> of_device_id **match)</span></span><br><span class="line">&#123;</span><br><span class="line">	<span class="comment">//......</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>该函数通过 of_device_id 匹配表来查找指定的节点。</p>
<p><strong>参数说明：</strong></p>
<ul>
<li>from：开始查找的节点，如果为 NULL 表示从根节点开始查找整个设备树。</li>
<li>matches： <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/include/linux/mod_devicetable.h#L241">of_device_id</a> 匹配表，也就是在此匹配表里面查找节点（该表包含要搜索的匹配项）。</li>
<li>match： 找到的匹配的 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/include/linux/mod_devicetable.h#L241">of_device_id</a>。</li>
</ul>
<p><strong>返回值：</strong>如果找到匹配的节点， 则返回对应的 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/include/linux/of.h#L51">struct device_node</a> 指针。如果未找到匹配的节点， 则返回 NULL。</p>
<p><a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/drivers/of/base.c#L1104">of_find_matching_node_and_match()</a>函数在设备树中遍历节点， 对每个节点使用 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/drivers/of/base.c#L1063">__of_match_node()</a> 函数进行匹配。 如果找到匹配的节点， 将返回该节点的指针， 并将 match 指针更新为匹配到的 of_device_id 条目， 函数会自动增加匹配节点的引用计数。下面是一个简单示例：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">include</span> <span class="string">&lt;linux/of.h&gt;</span></span></span><br><span class="line"><span class="type">static</span> <span class="type">const</span> <span class="class"><span class="keyword">struct</span> <span class="title">of_device_id</span> <span class="title">my_match_table</span>[] =</span> &#123;</span><br><span class="line">    &#123; .compatible = <span class="string">&quot;vendor,device&quot;</span> &#125;,</span><br><span class="line">    &#123; <span class="comment">/* sentinel */</span> &#125;</span><br><span class="line">&#125;;</span><br><span class="line"><span class="type">const</span> <span class="class"><span class="keyword">struct</span> <span class="title">of_device_id</span> *<span class="title">match</span>;</span></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">device_node</span> *<span class="title">np</span>;</span></span><br><span class="line"><span class="comment">// 从根节点开始查找匹配的节点</span></span><br><span class="line">np = of_find_matching_node_and_match(<span class="literal">NULL</span>, my_match_table, &amp;match);</span><br></pre></td></tr></table></figure>

<p>我们定义了一个 of_device_id 匹配表 my_match_table， 其中包含了一个兼容性字符串为”vendor,device”的匹配项。 然后， 我们使用 of_find_matching_node_and_match 函数从根节点开始查找匹配的节点。  </p>
<h3 id="2-2-查找父子节点"><a href="#2-2-查找父子节点" class="headerlink" title="2.2 查找父子节点"></a><font size=3>2.2 查找父子节点</font></h3><h4 id="2-2-1-of-get-parent"><a href="#2-2-1-of-get-parent" class="headerlink" title="2.2.1 of_get_parent() "></a><font size=3>2.2.1 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/drivers/of/base.c#L669">of_get_parent()</a> </font></h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">struct</span> device_node *<span class="title function_">of_get_parent</span><span class="params">(<span class="type">const</span> <span class="keyword">struct</span> device_node *node)</span></span><br><span class="line">&#123;</span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">device_node</span> *<span class="title">np</span>;</span></span><br><span class="line">	<span class="type">unsigned</span> <span class="type">long</span> flags;</span><br><span class="line"></span><br><span class="line">	<span class="keyword">if</span> (!node)</span><br><span class="line">		<span class="keyword">return</span> <span class="literal">NULL</span>;</span><br><span class="line"></span><br><span class="line">	raw_spin_lock_irqsave(&amp;devtree_lock, flags);</span><br><span class="line">	np = of_node_get(node-&gt;parent);</span><br><span class="line">	raw_spin_unlock_irqrestore(&amp;devtree_lock, flags);</span><br><span class="line">	<span class="keyword">return</span> np;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>该函数接收一个指向设备树节点的指针 node， 并返回该节点的父节点（如果有父节点的话）的指针。  </p>
<p><strong>参数说明：</strong></p>
<ul>
<li>node： 要获取父节点的设备树节点指针。</li>
</ul>
<p><strong>返回值：</strong>如果找到匹配的节点， 则返回对应的 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/include/linux/of.h#L51">struct device_node</a> 指针。如果未找到匹配的节点， 则返回 NULL。  </p>
<p>使用 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/drivers/of/base.c#L669">of_get_parent()</a> 函数时， 可以将特定的设备树节点作为参数传递给函数， 然后它将返回该节点的父节点。 这对于在设备树中导航和访问节点之间的层次关系非常有用。  </p>
<p>父节点在设备树中表示了节点之间的层次结构关系。 通过获取父节点， 我们可以访问上一级节点的属性和配置信息， 从而更好地理解设备树中的节点之间的关系。  </p>
<h4 id="2-2-2-of-get-next-parent"><a href="#2-2-2-of-get-next-parent" class="headerlink" title="2.2.2 of_get_next_parent()"></a><font size=3>2.2.2 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/drivers/of/base.c#L702">of_get_next_parent()</a></font></h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">struct</span> device_node *<span class="title function_">of_get_next_parent</span><span class="params">(<span class="keyword">struct</span> device_node *node)</span></span><br><span class="line">&#123;</span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">device_node</span> *<span class="title">parent</span>;</span></span><br><span class="line">	<span class="type">unsigned</span> <span class="type">long</span> flags;</span><br><span class="line"></span><br><span class="line">	<span class="keyword">if</span> (!node)</span><br><span class="line">		<span class="keyword">return</span> <span class="literal">NULL</span>;</span><br><span class="line"></span><br><span class="line">	raw_spin_lock_irqsave(&amp;devtree_lock, flags);</span><br><span class="line">	parent = of_node_get(node-&gt;parent);</span><br><span class="line">	of_node_put(node);</span><br><span class="line">	raw_spin_unlock_irqrestore(&amp;devtree_lock, flags);</span><br><span class="line">	<span class="keyword">return</span> parent;</span><br><span class="line">&#125;</span><br><span class="line">EXPORT_SYMBOL(of_get_next_parent);</span><br></pre></td></tr></table></figure>

<p>这个函数名比较奇怪，怎么可能有“ next parent”？它实际上也是找到 device_node 的父节点，跟 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/drivers/of/base.c#L669">of_get_parent()</a> 的返回结果是一样的。差别在于它多调用 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/drivers/of/dynamic.c#L40">of_node_put()</a> 函数，把 node 节点的引用计数减少了 1。这意味着调用 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/drivers/of/base.c#L702">of_get_next_parent()</a> 之后，我们不再需要调用 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/drivers/of/dynamic.c#L40">of_node_put()</a> 释放 node 节点      </p>
<p><strong>参数说明：</strong></p>
<ul>
<li>node： 要获取父节点的设备树节点指针。</li>
</ul>
<p><strong>返回值：</strong>如果找到匹配的节点， 则返回对应的 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/include/linux/of.h#L51">struct device_node</a> 指针。如果未找到匹配的节点， 则返回 NULL。  </p>
<h4 id="2-2-3-of-get-next-child"><a href="#2-2-3-of-get-next-child" class="headerlink" title="2.2.3 of_get_next_child()"></a><font size=3>2.2.3 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/drivers/of/base.c#L737">of_get_next_child()</a></font></h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">struct</span> device_node *<span class="title function_">of_get_next_child</span><span class="params">(<span class="type">const</span> <span class="keyword">struct</span> device_node *node,</span></span><br><span class="line"><span class="params">	<span class="keyword">struct</span> device_node *prev)</span></span><br><span class="line">&#123;</span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">device_node</span> *<span class="title">next</span>;</span></span><br><span class="line">	<span class="type">unsigned</span> <span class="type">long</span> flags;</span><br><span class="line"></span><br><span class="line">	raw_spin_lock_irqsave(&amp;devtree_lock, flags);</span><br><span class="line">	next = __of_get_next_child(node, prev);</span><br><span class="line">	raw_spin_unlock_irqrestore(&amp;devtree_lock, flags);</span><br><span class="line">	<span class="keyword">return</span> next;</span><br><span class="line">&#125;</span><br><span class="line">EXPORT_SYMBOL(of_get_next_child);</span><br></pre></td></tr></table></figure>

<p>该函数函数用于获取设备树节点的下一个子节点。   </p>
<p><strong>参数说明：</strong></p>
<ul>
<li>node： 当前节点， 用于指定要获取子节点的起始节点。</li>
<li>prev： 上一个子节点， 用于指定从哪个子节点开始获取下一个子节点。 如果为 NULL， 则从起始节点的第一个子节点开始。</li>
</ul>
<p><strong>返回值：</strong>如果找到匹配的节点， 则返回对应的 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/include/linux/of.h#L51">struct device_node</a> 指针。如果未找到匹配的节点， 则返回 NULL。  </p>
<p>使用 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/drivers/of/base.c#L737">of_get_next_child()</a> 函数时， 可以传递当前节点以及上一个子节点作为参数。 函数将从上一个子节点的下一个节点开始， 查找并返回下一个子节点。设备树中的子节点表示了节点之间的层次关系。 通过获取子节点， 可以遍历和访问当前节点的所有子节点， 以便进一步处理它们的属性和配置信息。</p>
<h4 id="2-2-4-of-get-next-available-child"><a href="#2-2-4-of-get-next-available-child" class="headerlink" title="2.2.4 of_get_next_available_child()"></a><font size=3>2.2.4 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/drivers/of/base.c#L759">of_get_next_available_child()</a></font></h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">struct</span> device_node *<span class="title function_">of_get_next_available_child</span><span class="params">(<span class="type">const</span> <span class="keyword">struct</span> device_node *node,</span></span><br><span class="line"><span class="params">	<span class="keyword">struct</span> device_node *prev)</span></span><br><span class="line">&#123;</span><br><span class="line">	<span class="comment">//......</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>该函数取出下一个“可用”的子节点，有些节点的 status 是“disabled”，那就会跳过这些节点。    </p>
<p><strong>参数说明：</strong></p>
<ul>
<li>node： 当前节点， 用于指定要获取子节点的起始节点。</li>
<li>prev： 上一个子节点， 用于指定从哪个子节点开始获取下一个子节点。 如果为 NULL， 则从起始节点的第一个子节点开始。</li>
</ul>
<p><strong>返回值：</strong>如果找到匹配的节点， 则返回对应的 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/include/linux/of.h#L51">struct device_node</a> 指针。如果未找到匹配的节点， 则返回 NULL。  </p>
<h4 id="2-2-5-of-get-child-by-name"><a href="#2-2-5-of-get-child-by-name" class="headerlink" title="2.2.5 of_get_child_by_name()"></a><font size=3>2.2.5 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/drivers/of/base.c#L815">of_get_child_by_name()</a></font></h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">struct</span> device_node *<span class="title function_">of_get_child_by_name</span><span class="params">(<span class="type">const</span> <span class="keyword">struct</span> device_node *node,</span></span><br><span class="line"><span class="params">				<span class="type">const</span> <span class="type">char</span> *name)</span></span><br><span class="line">&#123;</span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">device_node</span> *<span class="title">child</span>;</span></span><br><span class="line"></span><br><span class="line">	for_each_child_of_node(node, child)</span><br><span class="line">		<span class="keyword">if</span> (child-&gt;name &amp;&amp; (of_node_cmp(child-&gt;name, name) == <span class="number">0</span>))</span><br><span class="line">			<span class="keyword">break</span>;</span><br><span class="line">	<span class="keyword">return</span> child;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>该函数根据名字取出子节点。</p>
<p><strong>参数说明：</strong></p>
<ul>
<li>node： 当前节点， 用于指定要获取子节点的起始节点。</li>
<li>name： 表示子节点的名字。</li>
</ul>
<p><strong>返回值：</strong>如果找到匹配的节点， 则返回对应的 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/include/linux/of.h#L51">struct device_node</a> 指针。如果未找到匹配的节点， 则返回 NULL。  </p>
<h3 id="2-3-获取属性"><a href="#2-3-获取属性" class="headerlink" title="2.3 获取属性"></a><font size=3>2.3 获取属性</font></h3><p>节点的属性信息里面保存了驱动所需要的内容，因此对于属性值的提取非常重要， Linux 内核中使用结构体 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/include/linux/of.h#L31">struct property</a> 表示属性：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">property</span> &#123;</span></span><br><span class="line">	<span class="type">char</span>	*name;</span><br><span class="line">	<span class="type">int</span>	length;</span><br><span class="line">	<span class="type">void</span>	*value;</span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">property</span> *<span class="title">next</span>;</span></span><br><span class="line"><span class="meta">#<span class="keyword">if</span> defined(CONFIG_OF_DYNAMIC) || defined(CONFIG_SPARC)</span></span><br><span class="line">	<span class="type">unsigned</span> <span class="type">long</span> _flags;</span><br><span class="line"><span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">if</span> defined(CONFIG_OF_PROMTREE)</span></span><br><span class="line">	<span class="type">unsigned</span> <span class="type">int</span> unique_id;</span><br><span class="line"><span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">if</span> defined(CONFIG_OF_KOBJ)</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">bin_attribute</span> <span class="title">attr</span>;</span></span><br><span class="line"><span class="meta">#<span class="keyword">endif</span></span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<h4 id="2-3-1-of-find-property"><a href="#2-3-1-of-find-property" class="headerlink" title="2.3.1 of_find_property()"></a><font size=3>2.3.1 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/drivers/of/base.c#L264">of_find_property()</a></font></h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">struct</span> property *<span class="title function_">of_find_property</span><span class="params">(<span class="type">const</span> <span class="keyword">struct</span> device_node *np,</span></span><br><span class="line"><span class="params">				  <span class="type">const</span> <span class="type">char</span> *name,</span></span><br><span class="line"><span class="params">				  <span class="type">int</span> *lenp)</span></span><br><span class="line">&#123;</span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">property</span> *<span class="title">pp</span>;</span></span><br><span class="line">	<span class="type">unsigned</span> <span class="type">long</span> flags;</span><br><span class="line"></span><br><span class="line">	raw_spin_lock_irqsave(&amp;devtree_lock, flags);</span><br><span class="line">	pp = __of_find_property(np, name, lenp);</span><br><span class="line">	raw_spin_unlock_irqrestore(&amp;devtree_lock, flags);</span><br><span class="line"></span><br><span class="line">	<span class="keyword">return</span> pp;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>该函数用于在节点 np 下查找指定名称 name 的属性。  </p>
<p><strong>参数说明：</strong></p>
<ul>
<li>np: 要查找的节点。</li>
<li>name: 要查找的属性的属性名。</li>
<li>lenp: 一个指向整数的指针， 用于接收属性值的字节数。</li>
</ul>
<p><strong>返回值：</strong>如果成功找到了指定名称的属性， 则返回对应的属性结构体指针 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/include/linux/of.h#L31">struct property *</a> ； 如果未找到， 则返回 NULL。  </p>
<p><strong>示例：</strong></p>
<p>在设备树中，节点大概是这样：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">xxx_node &#123;</span><br><span class="line">	xxx_pp_name = “hello”;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>上述节点中，“ xxx_pp_name”就是属性的名字，值的长度是 6。  </p>
<h4 id="2-3-2-of-property-count-elems-of-size"><a href="#2-3-2-of-property-count-elems-of-size" class="headerlink" title="2.3.2 of_property_count_elems_of_size()"></a><font size=3>2.3.2 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/drivers/of/property.c#L31">of_property_count_elems_of_size()</a></font></h4><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="title function_">of_property_count_elems_of_size</span><span class="params">(<span class="type">const</span> <span class="keyword">struct</span> device_node *np,</span></span><br><span class="line"><span class="params">				<span class="type">const</span> <span class="type">char</span> *propname, <span class="type">int</span> elem_size)</span></span><br><span class="line">&#123;</span><br><span class="line">	<span class="comment">//......</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>该函数在设备树中的设备节点下查找指定名称的属性， 并获取该属性中元素的数量。 调用该函数可以用于获取设备树属性中某个属性的元素数量， 比如一个字符串列表的元素数量或一个整数数组的元素数量等，在比如我们常见的 reg 属性值就是一个数组，那么使用此函数可以获取到这个数组的大小 。    </p>
<p><strong>参数说明：</strong></p>
<ul>
<li>np: 设备节点。</li>
<li>propname: 需要获取元素数量的属性名。</li>
<li>elem_size: 单个元素的尺寸。</li>
</ul>
<p><strong>返回值：</strong>如果成功获取了指定属性中元素的数量， 则返回该数量； 如果未找到属性或属性中没有元素， 则返回 0。  </p>
<p><strong>示例：</strong></p>
<p>在设备树中，节点大概是这样：  </p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">xxx_node &#123;</span><br><span class="line">	xxx_pp_name = &lt;<span class="number">0x50000000</span> <span class="number">1024</span>&gt; &lt;<span class="number">0x60000000</span> <span class="number">2048</span>&gt;;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<ul>
<li>调用 of_property_count_elems_of_size(np, “xxx_pp_name”, 8)时，返回值是 2；  </li>
<li>调用 of_property_count_elems_of_size(np, “xxx_pp_name”, 4)时，返回值是 4。</li>
</ul>
<h4 id="2-3-3-读数组-u8-u16-u32-u64"><a href="#2-3-3-读数组-u8-u16-u32-u64" class="headerlink" title="2.3.3 读数组 u8&#x2F;u16&#x2F;u32&#x2F;u64"></a><font size=3>2.3.3 读数组 u8&#x2F;u16&#x2F;u32&#x2F;u64</font></h4><p>下面四个函数定义在：<a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/drivers/of/property.c">property.c - drivers&#x2F;of&#x2F;property.c</a></p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//从指定属性中读取变长的 u8 数组</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">of_property_read_variable_u8_array</span><span class="params">(<span class="type">const</span> <span class="keyword">struct</span> device_node *np,</span></span><br><span class="line"><span class="params">					<span class="type">const</span> <span class="type">char</span> *propname, u8 *out_values,</span></span><br><span class="line"><span class="params">					<span class="type">size_t</span> sz_min, <span class="type">size_t</span> sz_max)</span>;</span><br><span class="line"><span class="comment">//从指定属性中读取变长的 u16 数组</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">of_property_read_variable_u16_array</span><span class="params">(<span class="type">const</span> <span class="keyword">struct</span> device_node *np,</span></span><br><span class="line"><span class="params">					<span class="type">const</span> <span class="type">char</span> *propname, u16 *out_values,</span></span><br><span class="line"><span class="params">					<span class="type">size_t</span> sz_min, <span class="type">size_t</span> sz_max)</span>;</span><br><span class="line"><span class="comment">//从指定属性中读取变长的 u32 数组</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">of_property_read_variable_u32_array</span><span class="params">(<span class="type">const</span> <span class="keyword">struct</span> device_node *np,</span></span><br><span class="line"><span class="params">			       <span class="type">const</span> <span class="type">char</span> *propname, u32 *out_values,</span></span><br><span class="line"><span class="params">			       <span class="type">size_t</span> sz_min, <span class="type">size_t</span> sz_max)</span>;</span><br><span class="line"><span class="comment">//从指定属性中读取变长的 u64 数组</span></span><br><span class="line"><span class="type">int</span> <span class="title function_">of_property_read_variable_u64_array</span><span class="params">(<span class="type">const</span> <span class="keyword">struct</span> device_node *np,</span></span><br><span class="line"><span class="params">			       <span class="type">const</span> <span class="type">char</span> *propname, u64 *out_values,</span></span><br><span class="line"><span class="params">			       <span class="type">size_t</span> sz_min, <span class="type">size_t</span> sz_max)</span></span><br></pre></td></tr></table></figure>

<p>这几个函数用于从设备树中读取指定属性名的变长数组。 通过提供设备节点、 属性名和输出数组的指针， 可以将设备树中的数组数据读取到指定的内存区域中。 同时， 还需要指定数组的最小大小和最大大小， 以确保读取到的数组符合预期的大小范围。</p>
<p><strong>参数说明：</strong></p>
<ul>
<li>np: 设备节点。propname: 要读取的属性名。</li>
<li>out_values: 用于存储读取到的 u8&#x2F;u16&#x2F;u32&#x2F;u64 数组的指针。</li>
<li>sz_min: 数组的最小大小。</li>
<li>sz_max: 数组的最大大小。</li>
</ul>
<p><strong>返回值：</strong>0，读取成功，负值，读取失败， -EINVAL 表示属性不存在， -ENODATA 表示没有要读取的数据， -EOVERFLOW 表示属性值列表太小。</p>
<p><strong>示例：</strong></p>
<p>在设备树中，节点大概是这样：  </p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">xxx_node &#123;</span><br><span class="line">	name2 = &lt;<span class="number">0x50000012</span> <span class="number">0x60000034</span>&gt;;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>调用 of_property_read_variable_u8_array (np, “name2”, out_values, 1, 10)时，out_values 中将会保存这 8 个字节： 0x12,0x00,0x00,0x50,0x34,0x00,0x00,0x60。</p>
<p>调用 of_property_read_variable_u16_array (np, “name2”, out_values, 1, 10)时，out_values 中将会保存这 4 个 16 位数值： 0x0012, 0x5000,0x0034,0x6000。</p>
<p>总之，<strong>这些函数要么能取到全部的数值，要么一个数值都取不到；如果值的长度在 sz_min 和 sz_max 之间，就返回全部的数值；否则一个数值都不返回。</strong>  </p>
<details class="folding-tag" blue><summary> 点击查看详情 </summary>
              <div class='content'>
              <p>从这几个函数衍生出下面一组函数：</p><ul><li>这里的四个函数会调用of_property_read_variable_uX_array ()</li></ul><p><a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/include/linux/of.h#L419">of_property_read_u8_array()</a>、<a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/include/linux/of.h#L467">of_property_read_u16_array()</a>、<a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/include/linux/of.h#L495">of_property_read_u32_array()</a>、<a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/include/linux/of.h#L523">of_property_read_u64_array()</a></p>
              </div>
            </details>  

<h4 id="2-3-4-读整数-u8-u16-u32-u64"><a href="#2-3-4-读整数-u8-u16-u32-u64" class="headerlink" title="2.3.4 读整数 u8&#x2F;u16&#x2F;u32&#x2F;u64"></a><font size=3>2.3.4 读整数 u8&#x2F;u16&#x2F;u32&#x2F;u64</font></h4><p>下面的三个函数定义在这里：<a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/include/linux/of.h">of.h - include&#x2F;linux&#x2F;of.h</a>的 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/include/linux/of.h#L1162">1162</a> - <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/include/linux/of.h#L1181">1181</a>：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">static</span> <span class="keyword">inline</span> <span class="type">int</span> <span class="title function_">of_property_read_u8</span><span class="params">(<span class="type">const</span> <span class="keyword">struct</span> device_node *np,</span></span><br><span class="line"><span class="params">				       <span class="type">const</span> <span class="type">char</span> *propname,</span></span><br><span class="line"><span class="params">				       u8 *out_value)</span></span><br><span class="line">&#123;</span><br><span class="line">	<span class="keyword">return</span> of_property_read_u8_array(np, propname, out_value, <span class="number">1</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="type">static</span> <span class="keyword">inline</span> <span class="type">int</span> <span class="title function_">of_property_read_u16</span><span class="params">(<span class="type">const</span> <span class="keyword">struct</span> device_node *np,</span></span><br><span class="line"><span class="params">				       <span class="type">const</span> <span class="type">char</span> *propname,</span></span><br><span class="line"><span class="params">				       u16 *out_value)</span></span><br><span class="line">&#123;</span><br><span class="line">	<span class="keyword">return</span> of_property_read_u16_array(np, propname, out_value, <span class="number">1</span>);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="type">static</span> <span class="keyword">inline</span> <span class="type">int</span> <span class="title function_">of_property_read_u32</span><span class="params">(<span class="type">const</span> <span class="keyword">struct</span> device_node *np,</span></span><br><span class="line"><span class="params">				       <span class="type">const</span> <span class="type">char</span> *propname,</span></span><br><span class="line"><span class="params">				       u32 *out_value)</span></span><br><span class="line">&#123;</span><br><span class="line">	<span class="keyword">return</span> of_property_read_u32_array(np, propname, out_value, <span class="number">1</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>读u64整数的函数与上面不太一样，定义在<a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/drivers/of/property.c#L302">property.c - drivers&#x2F;of&#x2F;property.c</a>：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="title function_">of_property_read_u64</span><span class="params">(<span class="type">const</span> <span class="keyword">struct</span> device_node *np, <span class="type">const</span> <span class="type">char</span> *propname,</span></span><br><span class="line"><span class="params">			 u64 *out_value)</span></span><br><span class="line">&#123;</span><br><span class="line">	<span class="type">const</span> __be32 *val = of_find_property_value_of_size(np, propname,</span><br><span class="line">						<span class="keyword">sizeof</span>(*out_value),</span><br><span class="line">						<span class="number">0</span>,</span><br><span class="line">						<span class="literal">NULL</span>);</span><br><span class="line"></span><br><span class="line">	<span class="keyword">if</span> (IS_ERR(val))</span><br><span class="line">		<span class="keyword">return</span> PTR_ERR(val);</span><br><span class="line"></span><br><span class="line">	*out_value = of_read_number(val, <span class="number">2</span>);</span><br><span class="line">	<span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><strong>示例：</strong></p>
<p>在设备树中，节点大概是这样：  </p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">xxx_node &#123;</span><br><span class="line">    name1 = &lt;<span class="number">0x50000000</span>&gt;;</span><br><span class="line">    name2 = &lt;<span class="number">0x50000000</span> <span class="number">0x60000000</span>&gt;;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>调用 of_property_read_u32 (np, “name1”, &amp;val)时， val 将得到值 0x50000000；  </p>
<p>调用 of_property_read_u64 (np, “name2”, &amp;val)时， val 将得到值 0x6000000050000000。  </p>
<h4 id="2-3-5-读某个整数-u32"><a href="#2-3-5-读某个整数-u32" class="headerlink" title="2.3.5 读某个整数 u32"></a><font size=3>2.3.5 读某个整数 u32</font></h4><p> <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/drivers/of/property.c#L98">of_property_read_u32_index()</a>函数用于读取某个u32的值：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="title function_">of_property_read_u32_index</span><span class="params">(<span class="type">const</span> <span class="keyword">struct</span> device_node *np,</span></span><br><span class="line"><span class="params">				       <span class="type">const</span> <span class="type">char</span> *propname,</span></span><br><span class="line"><span class="params">				       u32 index, u32 *out_value)</span></span><br><span class="line">&#123;</span><br><span class="line">	<span class="type">const</span> u32 *val = of_find_property_value_of_size(np, propname,</span><br><span class="line">					((index + <span class="number">1</span>) * <span class="keyword">sizeof</span>(*out_value)),</span><br><span class="line">					<span class="number">0</span>,</span><br><span class="line">					<span class="literal">NULL</span>);</span><br><span class="line"></span><br><span class="line">	<span class="keyword">if</span> (IS_ERR(val))</span><br><span class="line">		<span class="keyword">return</span> PTR_ERR(val);</span><br><span class="line"></span><br><span class="line">	*out_value = be32_to_cpup(((__be32 *)val) + index);</span><br><span class="line">	<span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>该函数在设备树中的设备节点下查找指定名称的属性， 并获取该属性在给定索引位置处的u32 类型的数据值。这个函数通常用于从设备树属性中读取特定索引位置的整数值。 通过指定属性名和索引，可以获取属性中指定位置的具体数值。  </p>
<p><strong>参数说明：</strong></p>
<ul>
<li>np: 设备节点。</li>
<li>propname: 要读取的属性名。</li>
<li>index: 要读取的属性值在属性中的索引， 索引从 0 开始。</li>
<li>out_value: 用于存储读取到的值的指针。</li>
</ul>
<p><strong>返回值：</strong>0 读取成功，负值，读取失败， -EINVAL 表示属性不存在， -ENODATA 表示没有要读取的数据， -EOVERFLOW 表示属性值列表太小。  </p>
<p><strong>示例：</strong></p>
<p>在设备树中，节点大概是这样：  </p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">xxx_node &#123;</span><br><span class="line">	name2 = &lt;<span class="number">0x50000000</span> <span class="number">0x60000000</span>&gt;;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>调用 of_property_read_u32 (np, “name2”, 1, &amp;val)时， val 将得到值 0x60000000。  </p>
<h4 id="2-3-6-读某个整数-u64"><a href="#2-3-6-读某个整数-u64" class="headerlink" title="2.3.6 读某个整数 u64"></a><font size=3>2.3.6 读某个整数 u64</font></h4><p><a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/drivers/of/property.c#L145">of_property_read_u64_index()</a>用于读取某个u64的值：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="title function_">of_property_read_u64_index</span><span class="params">(<span class="type">const</span> <span class="keyword">struct</span> device_node *np,</span></span><br><span class="line"><span class="params">				       <span class="type">const</span> <span class="type">char</span> *propname,</span></span><br><span class="line"><span class="params">				       u32 index, u64 *out_value)</span></span><br><span class="line">&#123;</span><br><span class="line">	<span class="type">const</span> u64 *val = of_find_property_value_of_size(np, propname,</span><br><span class="line">					((index + <span class="number">1</span>) * <span class="keyword">sizeof</span>(*out_value)),</span><br><span class="line">					<span class="number">0</span>, <span class="literal">NULL</span>);</span><br><span class="line"></span><br><span class="line">	<span class="keyword">if</span> (IS_ERR(val))</span><br><span class="line">		<span class="keyword">return</span> PTR_ERR(val);</span><br><span class="line"></span><br><span class="line">	*out_value = be64_to_cpup(((__be64 *)val) + index);</span><br><span class="line">	<span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>该函数在设备树中的设备节点下查找指定名称的属性， 并获取该属性在给定索引位置处的u64 类型的数据值。这个函数通常用于从设备树属性中读取特定索引位置的 64 位整数值。 通过指定属性名和索引， 可以获取属性中指定位置的具体数值。    </p>
<p><strong>参数说明：</strong></p>
<ul>
<li>np: 设备节点。</li>
<li>propname: 要读取的属性名。</li>
<li>index: 要读取的属性值在属性中的索引， 索引从 0 开始。</li>
<li>out_value: 用于存储读取到的值的指针。</li>
</ul>
<p><strong>返回值：</strong>0 读取成功，负值，读取失败， -EINVAL 表示属性不存在， -ENODATA 表示没有要读取的数据， -EOVERFLOW 表示属性值列表太小。  </p>
<h4 id="2-3-7-读字符串"><a href="#2-3-7-读字符串" class="headerlink" title="2.3.7 读字符串"></a><font size=3>2.3.7 读字符串</font></h4><p><a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/drivers/of/property.c#L378">of_property_read_string()</a>函数用于读取属性中字符串值：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="title function_">of_property_read_string</span><span class="params">(<span class="type">const</span> <span class="keyword">struct</span> device_node *np, <span class="type">const</span> <span class="type">char</span> *propname,</span></span><br><span class="line"><span class="params">				<span class="type">const</span> <span class="type">char</span> **out_string)</span></span><br><span class="line">&#123;</span><br><span class="line">	<span class="type">const</span> <span class="class"><span class="keyword">struct</span> <span class="title">property</span> *<span class="title">prop</span> =</span> of_find_property(np, propname, <span class="literal">NULL</span>);</span><br><span class="line">	<span class="keyword">if</span> (!prop)</span><br><span class="line">		<span class="keyword">return</span> -EINVAL;</span><br><span class="line">	<span class="keyword">if</span> (!prop-&gt;value)</span><br><span class="line">		<span class="keyword">return</span> -ENODATA;</span><br><span class="line">	<span class="keyword">if</span> (strnlen(prop-&gt;value, prop-&gt;length) &gt;= prop-&gt;length)</span><br><span class="line">		<span class="keyword">return</span> -EILSEQ;</span><br><span class="line">	*out_string = prop-&gt;value;</span><br><span class="line">	<span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>该函数在设备树中的设备节点下查找指定名称的属性， 并获取该属性的字符串值， 最后返回读取到的字符串的指针， 通常用于从设备树属性中读取字符串值。 通过指定属性名， 可以获取属性中的字符串数据。  </p>
<p><strong>参数说明：</strong></p>
<ul>
<li>np: 设备节点。</li>
<li>propname: 要读取的属性名。</li>
<li>out_string: 用于存储读取到的字符串的指针。</li>
</ul>
<p><strong>返回值：</strong>如果成功读取到了指定属性的字符串， 则返回 0； 如果未找到属性或读取失败， 则返回相应的错误码。  </p>
<h4 id="2-3-8-读获取-address-cells"><a href="#2-3-8-读获取-address-cells" class="headerlink" title="2.3.8 读获取#address-cells  "></a><font size=3>2.3.8 读获取#address-cells  </font></h4><p><a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/drivers/of/base.c#L81">of_n_addr_cells()</a>函数用于读取#address-cells 属性值 ：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="title function_">of_n_addr_cells</span><span class="params">(<span class="keyword">struct</span> device_node *np)</span></span><br><span class="line">&#123;</span><br><span class="line">	u32 cells;</span><br><span class="line"></span><br><span class="line">	<span class="keyword">do</span> &#123;</span><br><span class="line">		<span class="keyword">if</span> (np-&gt;parent)</span><br><span class="line">			np = np-&gt;parent;</span><br><span class="line">		<span class="keyword">if</span> (!of_property_read_u32(np, <span class="string">&quot;#address-cells&quot;</span>, &amp;cells))</span><br><span class="line">			<span class="keyword">return</span> cells;</span><br><span class="line">	&#125; <span class="keyword">while</span> (np-&gt;parent);</span><br><span class="line">	<span class="comment">/* No #address-cells property for the root node */</span></span><br><span class="line">	<span class="keyword">return</span> OF_ROOT_NODE_ADDR_CELLS_DEFAULT;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><strong>参数说明：</strong></p>
<ul>
<li>np: 要查找的节点。</li>
</ul>
<p><strong>返回值：</strong>获取到的#address-cells 属性值。  </p>
<h4 id="2-3-9-读取-size-cells"><a href="#2-3-9-读取-size-cells" class="headerlink" title="2.3.9 读取#size-cells  "></a><font size=3>2.3.9 读取#size-cells  </font></h4><p><a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/drivers/of/base.c#L96">of_n_size_cells()</a>用于读取#size-cells 属性值：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="title function_">of_n_size_cells</span><span class="params">(<span class="keyword">struct</span> device_node *np)</span></span><br><span class="line">&#123;</span><br><span class="line">	u32 cells;</span><br><span class="line"></span><br><span class="line">	<span class="keyword">do</span> &#123;</span><br><span class="line">		<span class="keyword">if</span> (np-&gt;parent)</span><br><span class="line">			np = np-&gt;parent;</span><br><span class="line">		<span class="keyword">if</span> (!of_property_read_u32(np, <span class="string">&quot;#size-cells&quot;</span>, &amp;cells))</span><br><span class="line">			<span class="keyword">return</span> cells;</span><br><span class="line">	&#125; <span class="keyword">while</span> (np-&gt;parent);</span><br><span class="line">	<span class="comment">/* No #size-cells property for the root node */</span></span><br><span class="line">	<span class="keyword">return</span> OF_ROOT_NODE_SIZE_CELLS_DEFAULT;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><strong>参数说明：</strong></p>
<ul>
<li>np: 要查找的节点。</li>
</ul>
<p><strong>返回值：</strong>获取到的#size-cells 属性值。  </p>
<h3 id="2-4-其他函数"><a href="#2-4-其他函数" class="headerlink" title="2.4 其他函数"></a><font size=3>2.4 其他函数</font></h3><h4 id="2-4-1-of-device-is-compatible"><a href="#2-4-1-of-device-is-compatible" class="headerlink" title="2.4.1 of_device_is_compatible()  "></a><font size=3>2.4.1 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/drivers/of/base.c#L541">of_device_is_compatible()</a>  </font></h4><p><a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/drivers/of/base.c#L541">of_device_is_compatible()</a> 用于函数用于查看节点的 compatible 属性是否有包含 compat 指定的字符串，也就是检查设备节点的兼容性 :</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="title function_">of_device_is_compatible</span><span class="params">(<span class="type">const</span> <span class="keyword">struct</span> device_node *device,</span></span><br><span class="line"><span class="params">		<span class="type">const</span> <span class="type">char</span> *compat)</span></span><br><span class="line">&#123;</span><br><span class="line">	<span class="type">unsigned</span> <span class="type">long</span> flags;</span><br><span class="line">	<span class="type">int</span> res;</span><br><span class="line"></span><br><span class="line">	raw_spin_lock_irqsave(&amp;devtree_lock, flags);</span><br><span class="line">	res = __of_device_is_compatible(device, compat, <span class="literal">NULL</span>, <span class="literal">NULL</span>);</span><br><span class="line">	raw_spin_unlock_irqrestore(&amp;devtree_lock, flags);</span><br><span class="line">	<span class="keyword">return</span> res;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><strong>参数说明：</strong></p>
<ul>
<li>device：设备节点。</li>
<li>compat：要查看的字符串。</li>
</ul>
<p><strong>返回值：</strong>0，节点的 compatible 属性中不包含 compat 指定的字符串； 正数，节点的 compatible属性中包含 compat 指定的字符串。    </p>
<h4 id="2-4-2-of-get-address"><a href="#2-4-2-of-get-address" class="headerlink" title="2.4.2 of_get_address() "></a><font size=3>2.4.2 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/drivers/of/address.c#L694">of_get_address()</a> </font></h4><p><a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/drivers/of/address.c#L694">of_get_address()</a>用于函数用于获取地址相关属性，主要是“reg”或者“assigned-addresses”属性值 :</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">const</span> __be32 *<span class="title function_">of_get_address</span><span class="params">(<span class="keyword">struct</span> device_node *dev, <span class="type">int</span> index, u64 *size,</span></span><br><span class="line"><span class="params">		    <span class="type">unsigned</span> <span class="type">int</span> *flags)</span></span><br><span class="line">&#123;</span><br><span class="line">	<span class="comment">//......</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><strong>参数说明：</strong></p>
<ul>
<li>dev：设备节点。</li>
<li>index：要读取的地址标号。</li>
<li>size：地址长度。</li>
<li>flags：参数，比如 IORESOURCE_IO、 IORESOURCE_MEM 等</li>
</ul>
<p><strong>返回值：</strong>读取到的地址数据首地址，为 NULL 的话表示读取失败。  </p>
<h4 id="2-4-3-of-translate-address"><a href="#2-4-3-of-translate-address" class="headerlink" title="2.4.3 of_translate_address()"></a><font size=3>2.4.3 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/drivers/of/address.c#L663">of_translate_address()</a></font></h4><p><a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/drivers/of/address.c#L663">of_translate_address()</a>用于函数负责将从设备树读取到的地址转换为物理地址：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">u64 <span class="title function_">of_translate_address</span><span class="params">(<span class="keyword">struct</span> device_node *dev, <span class="type">const</span> __be32 *in_addr)</span></span><br><span class="line">&#123;</span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">device_node</span> *<span class="title">host</span>;</span></span><br><span class="line">	u64 ret;</span><br><span class="line"></span><br><span class="line">	ret = __of_translate_address(dev, in_addr, <span class="string">&quot;ranges&quot;</span>, &amp;host);</span><br><span class="line">	<span class="keyword">if</span> (host) &#123;</span><br><span class="line">		of_node_put(host);</span><br><span class="line">		<span class="keyword">return</span> OF_BAD_ADDR;</span><br><span class="line">	&#125;</span><br><span class="line"></span><br><span class="line">	<span class="keyword">return</span> ret;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><strong>参数说明：</strong></p>
<ul>
<li>dev：设备节点。</li>
<li>in_addr：要转换的地址。</li>
</ul>
<p><strong>返回值：</strong>得到的物理地址，如果为 OF_BAD_ADDR 的话表示转换失败。  </p>
<h4 id="2-4-4-of-address-to-resource"><a href="#2-4-4-of-address-to-resource" class="headerlink" title="2.4.4 of_address_to_resource()"></a><font size=3>2.4.4 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/drivers/of/address.c#L780">of_address_to_resource()</a></font></h4><p><a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/drivers/of/address.c#L780">of_address_to_resource()</a>函数看名字像是从设备树里面提取资源值，但是本质上就是将 reg 属性值，然后将其转换为 resource 结构体类型：  </p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">int</span> <span class="title function_">of_address_to_resource</span><span class="params">(<span class="keyword">struct</span> device_node *dev, <span class="type">int</span> index,</span></span><br><span class="line"><span class="params">			   <span class="keyword">struct</span> resource *r)</span></span><br><span class="line">&#123;</span><br><span class="line">	<span class="type">const</span> __be32	*addrp;</span><br><span class="line">	u64		size;</span><br><span class="line">	<span class="type">unsigned</span> <span class="type">int</span>	flags;</span><br><span class="line">	<span class="type">const</span> <span class="type">char</span>	*name = <span class="literal">NULL</span>;</span><br><span class="line"></span><br><span class="line">	addrp = of_get_address(dev, index, &amp;size, &amp;flags);</span><br><span class="line">	<span class="keyword">if</span> (addrp == <span class="literal">NULL</span>)</span><br><span class="line">		<span class="keyword">return</span> -EINVAL;</span><br><span class="line"></span><br><span class="line">	<span class="comment">/* Get optional &quot;reg-names&quot; property to add a name to a resource */</span></span><br><span class="line">	of_property_read_string_index(dev, <span class="string">&quot;reg-names&quot;</span>,	index, &amp;name);</span><br><span class="line"></span><br><span class="line">	<span class="keyword">return</span> __of_address_to_resource(dev, addrp, size, flags, name, r);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><strong>参数说明：</strong></p>
<ul>
<li>dev：设备节点。</li>
<li>index：地址资源标号。</li>
<li>r：得到的 resource 类型的资源值。</li>
</ul>
<p><strong>返回值：</strong>0，成功；负值，失败。    </p>
<details class="folding-tag" blue><summary> 关于resource </summary>
              <div class='content'>
              <p>IIC、 SPI、 GPIO 等这些外设都有对应的寄存器，这些寄存器其实就是一组内存空间， Linux内核使用 resource 结构体来描述一段内存空间，“resource”翻译出来就是“资源”，因此用 resource结构体描述的都是设备资源信息，resource 结构体定义在文件 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/include/linux/ioport.h#L19">ioport.h - include&#x2F;linux&#x2F;ioport.h</a>中，定义如下：</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">resource</span> &#123;</span></span><br><span class="line">	<span class="type">resource_size_t</span> start;</span><br><span class="line">	<span class="type">resource_size_t</span> end;</span><br><span class="line">	<span class="type">const</span> <span class="type">char</span> *name;</span><br><span class="line">	<span class="type">unsigned</span> <span class="type">long</span> flags;</span><br><span class="line">	<span class="type">unsigned</span> <span class="type">long</span> desc;</span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">resource</span> *<span class="title">parent</span>, *<span class="title">sibling</span>, *<span class="title">child</span>;</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>对于 32 位的 SOC 来说， resource_size_t 是 u32 类型的。其中 start 表示开始地址， end 表示结束地址， name 是这个资源的名字， flags 是资源标志位，一般表示资源类型，可选的资源标志定义在文件 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/include/linux/ioport.h#L29">ioport.h - include&#x2F;linux&#x2F;ioport.h</a> 中，如下所示  </p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="keyword">define</span> IORESOURCE_BITS		0x000000ff	<span class="comment">/* Bus-specific bits */</span></span></span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> IORESOURCE_TYPE_BITS	0x00001f00	<span class="comment">/* Resource type */</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> IORESOURCE_IO		0x00000100	<span class="comment">/* PCI/ISA I/O ports */</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> IORESOURCE_MEM		0x00000200</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> IORESOURCE_REG		0x00000300	<span class="comment">/* Register offsets */</span></span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> IORESOURCE_IRQ		0x00000400</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> IORESOURCE_DMA		0x00000800</span></span><br><span class="line"><span class="meta">#<span class="keyword">define</span> IORESOURCE_BUS		0x00001000</span></span><br><span class="line"><span class="comment">//......</span></span><br></pre></td></tr></table></figure><p>一般最常见的资源标志就是 IORESOURCE_MEM 、 IORESOURCE_REG 和IORESOURCE_IRQ 等。  </p>
              </div>
            </details>

<h4 id="2-4-5-of-iomap"><a href="#2-4-5-of-iomap" class="headerlink" title="2.4.5 of_iomap()"></a><font size=3>2.4.5 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/drivers/of/address.c#L826">of_iomap()</a></font></h4><p><a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/drivers/of/address.c#L826">of_iomap()</a>函数用于直接内存映射，以前我们会通过 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/arch/arm/include/asm/io.h#L400">ioremap()</a> 函数来完成物理地址到虚拟地址的映射，采用设备树以后就可以直接通过 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/drivers/of/address.c#L826">of_iomap()</a> 函数来获取内存地址所对应的虚拟地址，不需要使用 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/arch/arm/include/asm/io.h#L400">ioremap()</a> 函数了。当然了，也可以使用 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/arch/arm/include/asm/io.h#L400">ioremap()</a> 函数来完成物理地址到虚拟地址的内存映射，只是在采用设备树以后，大部分的驱动都使用  <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/drivers/of/address.c#L826">of_iomap()</a> 函数了。  <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/drivers/of/address.c#L826">of_iomap()</a> 函数本质上也是将 reg 属性中地址信息转换为虚拟地址，如果 reg 属性有多段的话，可以通过 index 参数指定要完成内存映射的是哪一段， <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/drivers/of/address.c#L826">of_iomap()</a> 函数原型如下  </p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">void</span> __iomem *<span class="title function_">of_iomap</span><span class="params">(<span class="keyword">struct</span> device_node *np, <span class="type">int</span> index)</span></span><br><span class="line">&#123;</span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">resource</span> <span class="title">res</span>;</span></span><br><span class="line"></span><br><span class="line">	<span class="keyword">if</span> (of_address_to_resource(np, index, &amp;res))</span><br><span class="line">		<span class="keyword">return</span> <span class="literal">NULL</span>;</span><br><span class="line"></span><br><span class="line">	<span class="keyword">return</span> ioremap(res.start, resource_size(&amp;res));</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p><strong>参数说明：</strong></p>
<ul>
<li>np：设备节点。</li>
<li>index： reg 属性中要完成内存映射的段，如果 reg 属性只有一段的话, index 就设置为 0。</li>
</ul>
<p><strong>返回值：</strong>经过内存映射后的虚拟内存首地址，如果为 NULL 的话表示内存映射失败。  </p>
<h2 id="3-platform-device-相关的函数"><a href="#3-platform-device-相关的函数" class="headerlink" title="3. platform_device 相关的函数  "></a><font size=3>3. platform_device 相关的函数  </font></h2><p>我们知道，设备树的节点有一些会转化成platform_device，针对这种类型的节点，也有几个相关的函数。</p>
<h3 id="3-1-of-find-device-by-node"><a href="#3-1-of-find-device-by-node" class="headerlink" title="3.1 of_find_device_by_node()"></a><font size=3>3.1 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/drivers/of/platform.c#L45">of_find_device_by_node()</a></font></h3><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">struct</span> platform_device *<span class="title function_">of_find_device_by_node</span><span class="params">(<span class="keyword">struct</span> device_node *np)</span></span><br><span class="line">&#123;</span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">device</span> *<span class="title">dev</span>;</span></span><br><span class="line"></span><br><span class="line">	dev = bus_find_device(&amp;platform_bus_type, <span class="literal">NULL</span>, np, of_dev_node_match);</span><br><span class="line">	<span class="keyword">return</span> dev ? to_platform_device(dev) : <span class="literal">NULL</span>;</span><br><span class="line">&#125;</span><br><span class="line">EXPORT_SYMBOL(of_find_device_by_node);</span><br></pre></td></tr></table></figure>

<p>设备树中的每一个节点，在内核里都有一个 device_node；我们可以使用device_node 去找到对应的 platform_device。  </p>
<h3 id="3-2-platform-get-resource"><a href="#3-2-platform-get-resource" class="headerlink" title="3.2 platform_get_resource()"></a><font size=3>3.2 <a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/drivers/base/platform.c#L60">platform_get_resource()</a></font></h3><p>这个函数跟设备树没什么关系，但是设备树中的节点被转换为platform_device 后，设备树中的 reg 属性、 interrupts 属性也会被转换为“ resource”，这个时候我们可以通过这个函数获取这些资源：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">struct</span> resource *<span class="title function_">platform_get_resource</span><span class="params">(<span class="keyword">struct</span> platform_device *dev,</span></span><br><span class="line"><span class="params">				       <span class="type">unsigned</span> <span class="type">int</span> type, <span class="type">unsigned</span> <span class="type">int</span> num)</span></span><br><span class="line">&#123;</span><br><span class="line">	<span class="type">int</span> i;</span><br><span class="line"></span><br><span class="line">	<span class="keyword">for</span> (i = <span class="number">0</span>; i &lt; dev-&gt;num_resources; i++) &#123;</span><br><span class="line">		<span class="class"><span class="keyword">struct</span> <span class="title">resource</span> *<span class="title">r</span> =</span> &amp;dev-&gt;resource[i];</span><br><span class="line"></span><br><span class="line">		<span class="keyword">if</span> (type == resource_type(r) &amp;&amp; num-- == <span class="number">0</span>)</span><br><span class="line">			<span class="keyword">return</span> r;</span><br><span class="line">	&#125;</span><br><span class="line">	<span class="keyword">return</span> <span class="literal">NULL</span>;</span><br><span class="line">&#125;</span><br><span class="line">EXPORT_SYMBOL_GPL(platform_get_resource);</span><br></pre></td></tr></table></figure>

<p><strong>参数说明：</strong></p>
<ul>
<li>dev：struct platform_device类型指针，包含了设备树节点的相关信息。</li>
<li>type：资源的类型，IORESOURCE_MEM、 IORESOURCE_REG、IORESOURCE_IRQ 等  </li>
<li>num：这类资源中的哪一个。</li>
</ul>
<p>对于设备树节点中的 reg 属性，它对应 IORESOURCE_MEM 类型的资源；对于设备树节点中的 interrupts 属性，它对应IORESOURCE_IRQ 类型的资源。  </p>
<h1 id="二、of函数使用实例"><a href="#二、of函数使用实例" class="headerlink" title="二、of函数使用实例"></a><font size=3>二、of函数使用实例</font></h1><h2 id="1-设备树节点准备"><a href="#1-设备树节点准备" class="headerlink" title="1. 设备树节点准备"></a><font size=3>1. 设备树节点准备</font></h2><p>这里可以在设备树中添加这样一个节点：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">alpha &#123;</span><br><span class="line">    <span class="meta">#address-cells = <span class="string">&lt;1&gt;</span>;</span></span><br><span class="line">    <span class="meta">#size-cells = <span class="string">&lt;1&gt;</span>;</span></span><br><span class="line">    compatible = <span class="string">&quot;simple-bus&quot;</span>;</span><br><span class="line"></span><br><span class="line">    sdev_led &#123;</span><br><span class="line">        <span class="meta">#address-cells = <span class="string">&lt;1&gt;</span>;</span></span><br><span class="line">        <span class="meta">#size-cells = <span class="string">&lt;1&gt;</span>;</span></span><br><span class="line">        compatible = <span class="string">&quot;led&quot;</span>;</span><br><span class="line">        status = <span class="string">&quot;okay&quot;</span>;</span><br><span class="line">        reg = &lt; <span class="number">0X020C406C</span> <span class="number">0X04</span> <span class="comment">/* CCM_CCGR1_BASE */</span></span><br><span class="line">                <span class="number">0X020E0068</span> <span class="number">0X04</span> <span class="comment">/* SW_MUX_GPIO1_IO03_BASE */</span></span><br><span class="line">                <span class="number">0X020E02F4</span> <span class="number">0X04</span> <span class="comment">/* SW_PAD_GPIO1_IO03_BASE */</span></span><br><span class="line">                <span class="number">0X0209C000</span> <span class="number">0X04</span> <span class="comment">/* GPIO1_DR_BASE */</span></span><br><span class="line">                <span class="number">0X0209C004</span> <span class="number">0X04</span> &gt;; <span class="comment">/* GPIO1_GDIR_BASE */</span></span><br><span class="line">    &#125;;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>为了避免#address-cells &#x3D; &lt;1&gt;; 和 #size-cells &#x3D; &lt;1&gt;;这两个属性改变根节点其他的节点的属性， 所以在这里创建了一个 alpha 节点。 在这个示例中， #address-cells 设置为 1 表示地址使用一个 32 位的单元， #size-cells 也设置为 1 表示大小使用一个 32 位的单元。  </p>
<p>第 4 行： 将 compatible 属性设置为”simple-bus”用于表示 alpha 节点的兼容性， 指明它是一个简单总线设备， 在转换 platform_device 的过程中， 会继续查找该节点的子节点。  </p>
<p>第 9 行： sdev_led 节点下的 compatible 属性为”led”， 表明该节点将会被转换为 platform_device。</p>
<p>第 11 行： 这个属性用于描述 sdev_led 节点的寄存器信息。可以看到有5个寄存器 。</p>
<p>这个节点在编译的时候报警告，但是并没有什么太大影响，这里可以先不管：</p>
<img data-src="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/02IMX6ULL%E5%B9%B3%E5%8F%B0/LV06-%E9%A9%B1%E5%8A%A8%E5%BC%80%E5%8F%91/LV06-10-%E8%AE%BE%E5%A4%87%E6%A0%91-04-%E8%AE%BE%E5%A4%87%E6%A0%91%E7%9A%84%E5%BA%94%E7%94%A8/img/image-20250309161117557.png" alt="image-20250309161117557" />

<p>我们之前用的是从tftp下载设备树，所以我们直接替换服务器中的设备树文件即可，然后重启设备，看一下节点情况：</p>
<img data-src="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/02IMX6ULL%E5%B9%B3%E5%8F%B0/LV06-%E9%A9%B1%E5%8A%A8%E5%BC%80%E5%8F%91/LV06-10-%E8%AE%BE%E5%A4%87%E6%A0%91-04-%E8%AE%BE%E5%A4%87%E6%A0%91%E7%9A%84%E5%BA%94%E7%94%A8/img/image-20250309161625812.png" alt="image-20250309161625812" />

<h2 id="2-of获取设备节点实例"><a href="#2-of获取设备节点实例" class="headerlink" title="2. of获取设备节点实例"></a><font size=3>2. of获取设备节点实例</font></h2><h3 id="2-1-demo源码"><a href="#2-1-demo源码" class="headerlink" title="2.1 demo源码"></a><font size=3>2.1 demo源码</font></h3><p>源码可以看这里：<a target="_blank" rel="noopener" href="https://gitee.com/sumumm/imx6ull-driver-demo/blob/master/11_device_tree/02_of_get_node/drivers_demo/sdriver_demo.c">11_device_tree&#x2F;02_of_get_node&#x2F;drivers_demo&#x2F;sdriver_demo.c · 苏木&#x2F;imx6ull-driver-demo - 码云 - 开源中国</a>中的函数<a target="_blank" rel="noopener" href="https://gitee.com/sumumm/imx6ull-driver-demo/blob/master/11_device_tree/02_of_get_node/drivers_demo/sdriver_demo.c#L73">of_get_node_test(void)</a>。</p>
<h3 id="2-2-开发板测试"><a href="#2-2-开发板测试" class="headerlink" title="2.2 开发板测试"></a><font size=3>2.2 开发板测试</font></h3><p>我们加载驱动，会看到如下打印信息：</p>
<img data-src="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/02IMX6ULL%E5%B9%B3%E5%8F%B0/LV06-%E9%A9%B1%E5%8A%A8%E5%BC%80%E5%8F%91/LV06-10-%E8%AE%BE%E5%A4%87%E6%A0%91-04-%E8%AE%BE%E5%A4%87%E6%A0%91%E7%9A%84%E5%BA%94%E7%94%A8/img/image-20250309162949432.png" alt="image-20250309162949432" />

<h2 id="3-of获取设备节点属性实例"><a href="#3-of获取设备节点属性实例" class="headerlink" title="3. of获取设备节点属性实例"></a><font size=3>3. of获取设备节点属性实例</font></h2><h3 id="3-1-demo源码"><a href="#3-1-demo源码" class="headerlink" title="3.1 demo源码"></a><font size=3>3.1 demo源码</font></h3><p>源码可以看这里：<a target="_blank" rel="noopener" href="https://gitee.com/sumumm/imx6ull-driver-demo/blob/master/11_device_tree/02_of_get_node/drivers_demo/sdriver_demo.c">11_device_tree&#x2F;02_of_get_node&#x2F;drivers_demo&#x2F;sdriver_demo.c · 苏木&#x2F;imx6ull-driver-demo - 码云 - 开源中国</a>中的函数<a target="_blank" rel="noopener" href="https://gitee.com/sumumm/imx6ull-driver-demo/blob/master/11_device_tree/02_of_get_node/drivers_demo/sdriver_demo.c#L117">of_get_node_property_test(void)</a>。</p>
<h3 id="3-2-开发板测试"><a href="#3-2-开发板测试" class="headerlink" title="3.2 开发板测试"></a><font size=3>3.2 开发板测试</font></h3><p>我们加载驱动，会看到如下打印信息：</p>
<img data-src="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/02IMX6ULL%E5%B9%B3%E5%8F%B0/LV06-%E9%A9%B1%E5%8A%A8%E5%BC%80%E5%8F%91/LV06-10-%E8%AE%BE%E5%A4%87%E6%A0%91-04-%E8%AE%BE%E5%A4%87%E6%A0%91%E7%9A%84%E5%BA%94%E7%94%A8/img/image-20250309164449464.png" alt="image-20250309164449464"  />

<h2 id="4-led实例"><a href="#4-led实例" class="headerlink" title="4. led实例"></a><font size=3>4. led实例</font></h2><p>上面已经可以从设备树获取对应的节点和属性了，那么我们来写一个led灯的demo，可以看这里：<a target="_blank" rel="noopener" href="https://gitee.com/sumumm/imx6ull-driver-demo/tree/master/11_device_tree/03_dts_led">11_device_tree&#x2F;03_dts_led · 苏木&#x2F;imx6ull-driver-demo - 码云 - 开源中国</a>。</p>
<h1 id="三、设备树下的平台设备驱动"><a href="#三、设备树下的平台设备驱动" class="headerlink" title="三、设备树下的平台设备驱动"></a><font size=3>三、设备树下的平台设备驱动</font></h1><p>前面我们学习了从 device_node 到 platform_device 的转换流程， 转换完成之后操作系统才能够识别和管理设备， 从而与 platform_driver 进行匹配 。这里我们就来学习一下吧。</p>
<h2 id="1-platform-device-如何与-platform-driver-配对"><a href="#1-platform-device-如何与-platform-driver-配对" class="headerlink" title="1. platform_device 如何与 platform_driver 配对  "></a><font size=3>1. platform_device 如何与 platform_driver 配对  </font></h2><p>从设备树转换得来的 platform_device 会被注册进内核里，以后当我们每注册一个 platform_driver 时，它们就会两两确定能否配对，如果能配对成功就调用 platform_driver 的 probe 函数。 （这里具体可以看《LV06-05-linux平台总线模型-03-平台总线的匹配.md》）</p>
<p>这里我们简单回顾一下，我们看一下<a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/drivers/base/platform.c#L950">platform_match()</a>函数：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">static</span> <span class="type">int</span> <span class="title function_">platform_match</span><span class="params">(<span class="keyword">struct</span> device *dev, <span class="keyword">struct</span> device_driver *drv)</span></span><br><span class="line">&#123;</span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">platform_device</span> *<span class="title">pdev</span> =</span> to_platform_device(dev);</span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">platform_driver</span> *<span class="title">pdrv</span> =</span> to_platform_driver(drv);</span><br><span class="line"></span><br><span class="line">	<span class="comment">/* （1）When driver_override is set, only bind to the matching driver */</span></span><br><span class="line">	<span class="keyword">if</span> (pdev-&gt;driver_override)</span><br><span class="line">		<span class="keyword">return</span> !<span class="built_in">strcmp</span>(pdev-&gt;driver_override, drv-&gt;name);</span><br><span class="line"></span><br><span class="line">	<span class="comment">/* （2）Attempt an OF style match first */</span></span><br><span class="line">	<span class="keyword">if</span> (of_driver_match_device(dev, drv))</span><br><span class="line">		<span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line"></span><br><span class="line">	<span class="comment">/* Then try ACPI style match */</span></span><br><span class="line">	<span class="keyword">if</span> (acpi_driver_match_device(dev, drv))</span><br><span class="line">		<span class="keyword">return</span> <span class="number">1</span>;</span><br><span class="line"></span><br><span class="line">	<span class="comment">/* （3）Then try to match against the id table */</span></span><br><span class="line">	<span class="keyword">if</span> (pdrv-&gt;id_table)</span><br><span class="line">		<span class="keyword">return</span> platform_match_id(pdrv-&gt;id_table, pdev) != <span class="literal">NULL</span>;</span><br><span class="line"></span><br><span class="line">	<span class="comment">/* （4）fall-back to driver name match */</span></span><br><span class="line">	<span class="keyword">return</span> (<span class="built_in">strcmp</span>(pdev-&gt;name, drv-&gt;name) == <span class="number">0</span>);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<h3 id="1-1-强制选择驱动"><a href="#1-1-强制选择驱动" class="headerlink" title="1.1 强制选择驱动"></a><font size=3>1.1 强制选择驱动</font></h3><ul>
<li>（1）最先比较：是否强制选择某个 driver 。（比较 platform_device.driver_override 和 platform_driver.driver.name）</li>
</ul>
<p>可以设置 platform_device 的 driver_override，强制选择某个 platform_driver。 </p>
<h3 id="1-2-设备树匹配"><a href="#1-2-设备树匹配" class="headerlink" title="1.2 设备树匹配"></a><font size=3>1.2 设备树匹配</font></h3><ul>
<li>（2）设备树信息。（比较platform_device.dev.of_node 和 platform_driver.driver.of_match_table）</li>
</ul>
<p>由设备树节点转换得来的 platform_device 中，含有一个结构体： of_node。它的类型为<a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/include/linux/of.h#L51">struct device_node</a></p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">device_node</span> &#123;</span></span><br><span class="line">	<span class="type">const</span> <span class="type">char</span> *name; <span class="comment">// 节点的name属性</span></span><br><span class="line">	<span class="type">const</span> <span class="type">char</span> *type; <span class="comment">// 节点的device_type属性</span></span><br><span class="line">	phandle phandle;</span><br><span class="line">	<span class="type">const</span> <span class="type">char</span> *full_name;</span><br><span class="line">	<span class="class"><span class="keyword">struct</span> <span class="title">fwnode_handle</span> <span class="title">fwnode</span>;</span></span><br><span class="line"></span><br><span class="line">	<span class="class"><span class="keyword">struct</span>	<span class="title">property</span> *<span class="title">properties</span>;</span><span class="comment">//含有compatible属性</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span>	<span class="title">property</span> *<span class="title">deadprops</span>;</span>	<span class="comment">/* removed properties */</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span>	<span class="title">device_node</span> *<span class="title">parent</span>;</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span>	<span class="title">device_node</span> *<span class="title">child</span>;</span></span><br><span class="line">	<span class="class"><span class="keyword">struct</span>	<span class="title">device_node</span> *<span class="title">sibling</span>;</span></span><br><span class="line">	<span class="comment">// ......</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>如果一个 platform_driver 支持设备树，它的platform_driver.driver.of_match_table 是一个数组，类型为<a target="_blank" rel="noopener" href="https://elixir.bootlin.com/linux/v4.19.71/source/include/linux/mod_devicetable.h#L241">struct of_device_id</a> ：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">of_device_id</span> &#123;</span></span><br><span class="line">	<span class="type">char</span>	name[<span class="number">32</span>];</span><br><span class="line">	<span class="type">char</span>	type[<span class="number">32</span>];</span><br><span class="line">	<span class="type">char</span>	compatible[<span class="number">128</span>];</span><br><span class="line">	<span class="type">const</span> <span class="type">void</span> *data;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>使用设备树信息来判断 dev 和 drv 是否配对时：</p>
<p>①首先，如果 of_match_table 中含有 compatible 值，就跟 dev 的 compatile 属性比较，若一致则成功，否则返回失败；</p>
<p>②其次，如果 of_match_table 中含有 type 值，就跟 dev 的 device_type 属性比较，若一致则成功，否则返回失败；</p>
<p>③最后，如果 of_match_table 中含有 name 值，就跟 dev 的 name 属性比较，若一致则成功，否则返回失败。</p>
<p>而设备树中建议不再使用 devcie_type 和 name 属性，所以基本上只使用设备节点的 compatible 属性来寻找匹配的 platform_driver。  </p>
<h3 id="1-3-id匹配"><a href="#1-3-id匹配" class="headerlink" title="1.3 id匹配"></a><font size=3>1.3 id匹配</font></h3><ul>
<li>（3）比较 platform_device_id （ 比较 platform_device. name 和 platform_driver.id_table[i].name）</li>
</ul>
<p>id_table 中可能有多项。 platform_driver.id_table 是“ platform_device_id”指针，表示该 drv支持若干个 device，它里面列出了各个 device 的{.name, .driver_data}，其中的“ name”表示该 drv 支持的设备的名字， driver_data 是些提供给该device 的私有数据。  </p>
<h3 id="1-4-name匹配"><a href="#1-4-name匹配" class="headerlink" title="1.4 name匹配"></a><font size=3>1.4 name匹配</font></h3><ul>
<li>（4）名称匹配，比较platform_device.name 和 platform_driver.driver.name</li>
</ul>
<p>platform_driver.id_table 可能为空，这时可以根据 platform_driver.driver.name 来寻找同名的platform_device。 </p>
<h3 id="1-5-总结"><a href="#1-5-总结" class="headerlink" title="1.5 总结"></a><font size=3>1.5 总结</font></h3><img data-src="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/02IMX6ULL%E5%B9%B3%E5%8F%B0/LV06-%E9%A9%B1%E5%8A%A8%E5%BC%80%E5%8F%91/LV06-10-%E8%AE%BE%E5%A4%87%E6%A0%91-04-%E8%AE%BE%E5%A4%87%E6%A0%91%E7%9A%84%E5%BA%94%E7%94%A8/img/image-20250119115206386.png" alt="image-20250119115206386" />

<h2 id="2-设备树匹配实例"><a href="#2-设备树匹配实例" class="headerlink" title="2. 设备树匹配实例"></a><font size=3>2. 设备树匹配实例</font></h2><h3 id="2-1-需要哪些条件？"><a href="#2-1-需要哪些条件？" class="headerlink" title="2.1 需要哪些条件？"></a><font size=3>2.1 需要哪些条件？</font></h3><p>在我们的工作中，驱动要求设备树节点提供什么，我们就得按这要求去编写设备树。匹配过程所要求的东西是固定的：  </p>
<ul>
<li>（1）设备树要有 compatible 属性，它的值是一个字符串</li>
</ul>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">/&#123;</span><br><span class="line">    alpha &#123;</span><br><span class="line">        <span class="meta">#address-cells = <span class="string">&lt;1&gt;</span>;</span></span><br><span class="line">        <span class="meta">#size-cells = <span class="string">&lt;1&gt;</span>;</span></span><br><span class="line">        compatible = <span class="string">&quot;simple-bus&quot;</span>;</span><br><span class="line"></span><br><span class="line">        sdev_led &#123;</span><br><span class="line">            <span class="meta">#address-cells = <span class="string">&lt;1&gt;</span>;</span></span><br><span class="line">            <span class="meta">#size-cells = <span class="string">&lt;1&gt;</span>;</span></span><br><span class="line">            compatible = <span class="string">&quot;led&quot;</span>;</span><br><span class="line">            status = <span class="string">&quot;okay&quot;</span>;</span><br><span class="line">            reg = &lt; <span class="number">0X020C406C</span> <span class="number">0X04</span> <span class="comment">/* CCM_CCGR1_BASE */</span></span><br><span class="line">                    <span class="number">0X020E0068</span> <span class="number">0X04</span> <span class="comment">/* SW_MUX_GPIO1_IO03_BASE */</span></span><br><span class="line">                    <span class="number">0X020E02F4</span> <span class="number">0X04</span> <span class="comment">/* SW_PAD_GPIO1_IO03_BASE */</span></span><br><span class="line">                    <span class="number">0X0209C000</span> <span class="number">0X04</span> <span class="comment">/* GPIO1_DR_BASE */</span></span><br><span class="line">                    <span class="number">0X0209C004</span> <span class="number">0X04</span> &gt;; <span class="comment">/* GPIO1_GDIR_BASE */</span></span><br><span class="line">        &#125;;</span><br><span class="line">    &#125;;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<ul>
<li>（2）platform_driver 中要有 of_match_table，其中一项的.compatible 成员设置为一个字符串</li>
</ul>
<p>我们需要定义一个设备树驱动匹配表：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/* 设备树匹配列表 */</span></span><br><span class="line"><span class="type">static</span> <span class="type">const</span> <span class="class"><span class="keyword">struct</span> <span class="title">of_device_id</span> <span class="title">led_of_match</span>[] =</span> &#123;</span><br><span class="line">	&#123; .compatible = <span class="string">&quot;led&quot;</span> &#125;, <span class="comment">// 这里用于匹配设备树中的 compatible 属性节点</span></span><br><span class="line">	&#123; <span class="comment">/* Sentinel */</span> &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<ul>
<li>（3）上述 2 个字符串要一致。</li>
</ul>
<h3 id="2-2-基本框架"><a href="#2-2-基本框架" class="headerlink" title="2.2 基本框架"></a><font size=3>2.2 基本框架</font></h3><p>定义platform_driver的时候要用上面的这个表：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 定义平台驱动结构体</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="type">static</span> <span class="class"><span class="keyword">struct</span> <span class="title">platform_driver</span> <span class="title">g_sdrv_platform</span> =</span> &#123;</span><br><span class="line">    .probe = sdrv_probe,   <span class="comment">// 平台设备的探测函数指针</span></span><br><span class="line">    .remove = sdrv_remove, <span class="comment">//  平台设备的移除函数指针</span></span><br><span class="line">    .driver = &#123;</span><br><span class="line">        .name = <span class="string">&quot;imx6ul-led-driver&quot;</span>, <span class="comment">// 和设备名称相同时，可以匹配成功</span></span><br><span class="line">                                   <span class="comment">// 会在 /sys/bus/platform/drivers中创建对应目录，即/sys/bus/platform/drivers/driver-name</span></span><br><span class="line">        .owner = THIS_MODULE,</span><br><span class="line">		.of_match_table	= led_of_match, <span class="comment">/* 设备树匹配表 */</span></span><br><span class="line">    &#125;,</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>基本框架如下：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">static</span> <span class="type">int</span> <span class="title function_">sdrv_probe</span><span class="params">(<span class="keyword">struct</span> platform_device *pdev)</span></span><br><span class="line">&#123;</span><br><span class="line">    PRT(<span class="string">&quot;probing platform device &amp; driver!pdev-&gt;name=%s\n&quot;</span>, pdev-&gt;name);</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="type">static</span> <span class="type">int</span> <span class="title function_">sdrv_remove</span><span class="params">(<span class="keyword">struct</span> platform_device *pdev)</span></span><br><span class="line">&#123;</span><br><span class="line">    PRT(<span class="string">&quot;removing platform driver!pdev-&gt;name=%s\n&quot;</span>, pdev-&gt;name);</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">/* 设备树匹配列表 */</span></span><br><span class="line"><span class="type">static</span> <span class="type">const</span> <span class="class"><span class="keyword">struct</span> <span class="title">of_device_id</span> <span class="title">led_of_match</span>[] =</span> &#123;</span><br><span class="line">	&#123; .compatible = <span class="string">&quot;led&quot;</span> &#125;, <span class="comment">// 这里用于匹配设备树中的 compatible 属性节点</span></span><br><span class="line">	&#123; <span class="comment">/* Sentinel */</span> &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 定义平台驱动结构体</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="type">static</span> <span class="class"><span class="keyword">struct</span> <span class="title">platform_driver</span> <span class="title">g_sdrv_platform</span> =</span> &#123;</span><br><span class="line">    .probe = sdrv_probe,   <span class="comment">// 平台设备的探测函数指针</span></span><br><span class="line">    .remove = sdrv_remove, <span class="comment">//  平台设备的移除函数指针</span></span><br><span class="line">    .driver = &#123;</span><br><span class="line">        .name = <span class="string">&quot;imx6ul-led-driver&quot;</span>, <span class="comment">// 和设备名称相同时，可以匹配成功</span></span><br><span class="line">                                   <span class="comment">// 会在 /sys/bus/platform/drivers中创建对应目录，即/sys/bus/platform/drivers/driver-name</span></span><br><span class="line">        .owner = THIS_MODULE,</span><br><span class="line">		.of_match_table	= led_of_match, <span class="comment">/* 设备树匹配表 */</span></span><br><span class="line">    &#125;,</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="type">static</span> __init <span class="type">int</span> <span class="title function_">sdrv_demo_init</span><span class="params">(<span class="type">void</span>)</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="type">int</span> ret = <span class="number">0</span>;</span><br><span class="line">	printk(<span class="string">&quot;*** [%s:%d]Build Time: %s %s, git version:%s LINUX_VERSION=%d.%d.%d ***\n&quot;</span>, __FUNCTION__,</span><br><span class="line">           __LINE__, KERNEL_KO_DATE, KERNEL_KO_TIME, KERNEL_KO_VERSION, </span><br><span class="line">           (LINUX_VERSION_CODE &gt;&gt; <span class="number">16</span>) &amp; <span class="number">0xff</span>, (LINUX_VERSION_CODE &gt;&gt; <span class="number">8</span>) &amp; <span class="number">0xff</span>, LINUX_VERSION_CODE &amp; <span class="number">0xff</span>);</span><br><span class="line"></span><br><span class="line">	<span class="comment">// 注册平台驱动</span></span><br><span class="line">    ret = platform_driver_register(&amp;g_sdrv_platform);</span><br><span class="line">    <span class="keyword">if</span> (ret) </span><br><span class="line">    &#123;</span><br><span class="line">        PRT(<span class="string">&quot;Failed to register platform driver!ret=%d\n&quot;</span>, ret);</span><br><span class="line">        <span class="keyword">goto</span> err_platform_driver_register;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//PRT(&quot;sdrv_demo module init success!\n&quot;);</span></span><br><span class="line">	<span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"></span><br><span class="line">err_platform_driver_register:</span><br><span class="line">    <span class="keyword">return</span> ret;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="type">static</span> __exit <span class="type">void</span> <span class="title function_">sdrv_demo_exit</span><span class="params">(<span class="type">void</span>)</span></span><br><span class="line">&#123;</span><br><span class="line">    <span class="comment">// 注销平台驱动</span></span><br><span class="line">    platform_driver_unregister(&amp;g_sdrv_platform);</span><br><span class="line">    <span class="comment">//PRT(&quot;sdrv_demo module exit!\n&quot;);</span></span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">module_init(sdrv_demo_init); <span class="comment">// 将__init定义的函数指定为驱动的入口函数</span></span><br><span class="line">module_exit(sdrv_demo_exit); <span class="comment">// 将__exit定义的函数指定为驱动的出口函数</span></span><br><span class="line"></span><br><span class="line"><span class="comment">/* 模块信息(通过 modinfo xxx.ko 查看) */</span></span><br><span class="line">MODULE_LICENSE(<span class="string">&quot;GPL v2&quot;</span>);            <span class="comment">/* 源码的许可证协议 */</span></span><br><span class="line">MODULE_AUTHOR(<span class="string">&quot;sumu&quot;</span>);               <span class="comment">/* 字符串常量内容为模块作者说明 */</span></span><br><span class="line">MODULE_DESCRIPTION(<span class="string">&quot;Description&quot;</span>);   <span class="comment">/* 字符串常量内容为模块功能说明 */</span></span><br><span class="line">MODULE_ALIAS(<span class="string">&quot;module&#x27;s other name&quot;</span>); <span class="comment">/* 字符串常量内容为模块别名 */</span></span><br></pre></td></tr></table></figure>

<h3 id="2-3-demo源码"><a href="#2-3-demo源码" class="headerlink" title="2.3 demo源码"></a><font size=3>2.3 demo源码</font></h3><p>demo源码可以看这里：<a target="_blank" rel="noopener" href="https://gitee.com/sumumm/imx6ull-driver-demo/tree/master/11_device_tree/04_platform_dtb_match">11_device_tree&#x2F;04_platform_dtb_match · 苏木&#x2F;imx6ull-driver-demo - 码云 - 开源中国</a></p>
<p>需要注意，这个demo中完成了平台设备驱动的设备树匹配过程，但是获取节点的信息的时候还是通过of相关函数获取，下一个demo我们再研究通过platform_device来获取节点信息。</p>
<h3 id="2-4-调试技巧"><a href="#2-4-调试技巧" class="headerlink" title="2.4 调试技巧"></a><font size=3>2.4 调试技巧</font></h3><ul>
<li>设备树节点</li>
</ul>
<p>我们换了设备树后就需要看一下是不是生成了正确的节点，可以到以下目录去看</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">ls /sys/firmware/devicetree/base</span><br><span class="line"><span class="meta prompt_"># </span><span class="language-bash">或者</span> </span><br><span class="line">ls /proc/device-tree/</span><br></pre></td></tr></table></figure>

<ul>
<li>platform_device查看</li>
</ul>
<p>我们创建的节点是会被转化为platform_device的，可以看这个目录：</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ls /sys/bus/platform/devices</span><br></pre></td></tr></table></figure>

<img data-src="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/02IMX6ULL%E5%B9%B3%E5%8F%B0/LV06-%E9%A9%B1%E5%8A%A8%E5%BC%80%E5%8F%91/LV06-10-%E8%AE%BE%E5%A4%87%E6%A0%91-04-%E8%AE%BE%E5%A4%87%E6%A0%91%E7%9A%84%E5%BA%94%E7%94%A8/img/image-20250309193144637.png" alt="image-20250309193144637" />

<ul>
<li>platform_driver 的信息</li>
</ul>
<p>以下目录含有注册进内核的所有 platform_driver：  </p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ls /sys/bus/platform/drivers</span><br></pre></td></tr></table></figure>

<img data-src="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/02IMX6ULL%E5%B9%B3%E5%8F%B0/LV06-%E9%A9%B1%E5%8A%A8%E5%BC%80%E5%8F%91/LV06-10-%E8%AE%BE%E5%A4%87%E6%A0%91-04-%E8%AE%BE%E5%A4%87%E6%A0%91%E7%9A%84%E5%BA%94%E7%94%A8/img/image-20250309193337157.png" alt="image-20250309193337157" />

<p>一个 driver 对应一个目录，进入某个目录后，如果它有配对的设备，可以直接看到。例如这里我们的imx6ul-led-driver就匹配了alpha：sdev_led设备。  </p>
<blockquote>
<p>注意： 一个平台设备只能配对一个平台驱动，一个平台驱动可以配对多个平台设备。  </p>
</blockquote>
<h2 id="3-从platform-device获取节点信息"><a href="#3-从platform-device获取节点信息" class="headerlink" title="3. 从platform_device获取节点信息"></a><font size=3>3. 从platform_device获取节点信息</font></h2><h3 id="3-1-怎么拿到节点？"><a href="#3-1-怎么拿到节点？" class="headerlink" title="3.1 怎么拿到节点？"></a><font size=3>3.1 怎么拿到节点？</font></h3><p>可以通过设备树节点指定资源， platform_driver 获得资源，那么 platform_drive怎么获得资源？ 我们看一下probe函数：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="type">static</span> <span class="type">int</span> <span class="title function_">sdrv_probe</span><span class="params">(<span class="keyword">struct</span> platform_device *pdev)</span></span><br><span class="line">&#123;</span><br><span class="line">    </span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>在匹配成功后，会传入platform_device的指针，我们前面知道，platform_device.dev.of_node中存储了节点的相关信息，我们完全可以根据这个来找到对应的节点：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">device_node</span>* <span class="title">np</span> =</span> pdev-&gt;dev.of_node;</span><br></pre></td></tr></table></figure>

<h3 id="3-2-demo源码"><a href="#3-2-demo源码" class="headerlink" title="3.2 demo源码"></a><font size=3>3.2 demo源码</font></h3><p>源码可以看这里：<a target="_blank" rel="noopener" href="https://gitee.com/sumumm/imx6ull-driver-demo/tree/master/11_device_tree/05_platform_get_node">11_device_tree&#x2F;05_platform_get_node · 苏木&#x2F;imx6ull-driver-demo - 码云 - 开源中国</a>，源码中是通过这行获取节点：</p>
<img data-src="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/02IMX6ULL%E5%B9%B3%E5%8F%B0/LV06-%E9%A9%B1%E5%8A%A8%E5%BC%80%E5%8F%91/LV06-10-%E8%AE%BE%E5%A4%87%E6%A0%91-04-%E8%AE%BE%E5%A4%87%E6%A0%91%E7%9A%84%E5%BA%94%E7%94%A8/img/image-20250309195107101.png" alt="image-20250309195107101" />

<h3 id="3-3-开发板测试"><a href="#3-3-开发板测试" class="headerlink" title="3.3 开发板测试"></a><font size=3>3.3 开发板测试</font></h3><p>我们加载驱动可以看到：</p>
<img data-src="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/02IMX6ULL%E5%B9%B3%E5%8F%B0/LV06-%E9%A9%B1%E5%8A%A8%E5%BC%80%E5%8F%91/LV06-10-%E8%AE%BE%E5%A4%87%E6%A0%91-04-%E8%AE%BE%E5%A4%87%E6%A0%91%E7%9A%84%E5%BA%94%E7%94%A8/img/image-20250309195026404.png" alt="image-20250309195026404" />


    </div>

    
    
    

    <footer class="post-footer">




    <div>
        
            <div style="text-align:center;color: #ccc;font-size:14px;">
            ----------本文结束
            <i class="fas fa-fan fa-spin" style="color: #FF1493; font-size: 1rem"></i>
            感谢您的阅读----------
            </div>
        
    </div>





  
  <div class="my_post_copyright"> 
    <p><span>文章标题:</span><a href="/post/3df14f88.html">LV06-10-设备树-04-设备树的应用</a></p>
    <p><span>文章作者:</span><a href="/" title="欢迎访问 《苏木》 的学习笔记">苏木</a></p>
    <p><span>发布时间:</span>2025年03月17日 - 07:45</p>
    <p><span>最后更新:</span>2025年06月14日 - 00:25</p>
    <p><span>原始链接:</span><a href="/post/3df14f88.html" title="LV06-10-设备树-04-设备树的应用">https://sumumm.github.io/post/3df14f88.html</a></p>
    <p><span>许可协议:</span><i class="fab fa-creative-commons"></i> <a rel="license" href= "https://creativecommons.org/licenses/by-nc-nd/4.0/" target="_blank" title="Attribution-NonCommercial-NoDerivatives 4.0 International (CC BY-NC-ND 4.0)">署名-非商业性使用-禁止演绎 4.0 国际</a> 转载请保留原文链接及作者。</p>  
  </div>
  


          <div class="post-tags">
              <a href="/tags/LV06-%E9%A9%B1%E5%8A%A8%E5%BC%80%E5%8F%91/" rel="tag"><i class="fa fa-tag"></i> LV06-驱动开发</a>
          </div>

        

          <div class="post-nav">
            <div class="post-nav-item">
                <a href="/post/238c1e95.html" rel="prev" title="LV06-10-设备树-05-ranges属性">
                  <i class="fa fa-angle-left"></i> LV06-10-设备树-05-ranges属性
                </a>
            </div>
            <div class="post-nav-item">
                <a href="/post/cb9c294a.html" rel="next" title="LV06-10-设备树-03-设备树深入分析">
                  LV06-10-设备树-03-设备树深入分析 <i class="fa fa-angle-right"></i>
                </a>
            </div>
          </div>
    </footer>
  </article>
</div>






</div>
  </main>

  <footer class="footer">
    <div class="footer-inner">

  <div class="copyright">
    &copy; 2017 – 
    <span itemprop="copyrightYear">2025</span>
    <span class="with-love">
      <i class="fa fa-heart"></i>
    </span>
    <span class="author" itemprop="copyrightHolder">苏木</span>
  </div>
<div class="wordcount">
  <span class="post-meta-item">
    <span class="post-meta-item-icon">
      <i class="fa fa-chart-line"></i>
    </span>
      <span>站点总字数：</span>
    <span title="站点总字数">3.7m</span>
  </span>
  <span class="post-meta-item">
    <span class="post-meta-item-icon">
      <i class="fa fa-coffee"></i>
    </span>
      <span>站点阅读时长 &asymp;</span>
    <span title="站点阅读时长">225:26</span>
  </span>
</div>




    <span id="sitetime"></span>
    <script defer language=javascript>
        function siteTime()
        {
            window.setTimeout("siteTime()", 1000);
            var seconds = 1000;
            var minutes = seconds * 60;
            var hours = minutes * 60;
            var days = hours * 24;
            var years = days * 365;
            var today = new Date();
            var todayYear = today.getFullYear();
            var todayMonth = today.getMonth()+1;
            var todayDate = today.getDate();
            var todayHour = today.getHours();
            var todayMinute = today.getMinutes();
            var todaySecond = today.getSeconds();
            /*==================================================
            Date.UTC() -- 返回date对象距世界标准时间(UTC)1970年1月1日午夜之间的毫秒数(时间戳)
            year        - 作为date对象的年份，为4位年份值
            month       - 0-11之间的整数，做为date对象的月份
            day         - 1-31之间的整数，做为date对象的天数
            hours       - 0(午夜24点)-23之间的整数，做为date对象的小时数
            minutes     - 0-59之间的整数，做为date对象的分钟数
            seconds     - 0-59之间的整数，做为date对象的秒数
            microseconds - 0-999之间的整数，做为date对象的毫秒数
            ==================================================*/
            var t1 = Date.UTC(2017, 
                              5, 
                              19, 
                              0, 
                              0, 
                              0); //北京时间
            var t2 = Date.UTC(todayYear,todayMonth,todayDate,todayHour,todayMinute,todaySecond);
            var diff = t2-t1;
            var diffYears = Math.floor(diff/years);
            var diffDays = Math.floor((diff/days)-diffYears*365);
            var diffHours = Math.floor((diff-(diffYears*365+diffDays)*days)/hours);
            var diffMinutes = Math.floor((diff-(diffYears*365+diffDays)*days-diffHours*hours)/minutes);
            var diffSeconds = Math.floor((diff-(diffYears*365+diffDays)*days-diffHours*hours-diffMinutes*minutes)/seconds);
            document.getElementById("sitetime").innerHTML="已在这里 "+diffYears+" 年 "+diffDays+" 天 "+diffHours+" 小时 "+diffMinutes+" 分钟 "+diffSeconds+" 秒";
        }
        siteTime();
    </script>



    </div>
  </footer>

  
  <div class="back-to-top" role="button" aria-label="返回顶部">
    <i class="fa fa-arrow-up fa-lg"></i>
    <span>0%</span>
  </div>
  <div class="reading-progress-bar"></div>

<noscript>
  <div class="noscript-warning">Theme NexT works best with JavaScript enabled</div>
</noscript>


  
  <script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.1/anime.min.js" integrity="sha256-XL2inqUJaslATFnHdJOi9GfQ60on8Wx1C2H8DYiN1xY=" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/next-theme-pjax/0.6.0/pjax.min.js" integrity="sha256-vxLn1tSKWD4dqbMRyv940UYw4sXgMtYcK6reefzZrao=" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/fancyapps-ui/5.0.28/fancybox/fancybox.umd.js" integrity="sha256-ytMJGN3toR+a84u7g7NuHm91VIR06Q41kMWDr2pq7Zo=" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/lozad.js/1.16.0/lozad.min.js" integrity="sha256-mOFREFhqmHeQbXpK2lp4nA3qooVgACfh88fpJftLBbc=" crossorigin="anonymous"></script>
<script src="/js/comments.js"></script><script src="/js/utils.js"></script><script src="/js/motion.js"></script><script src="/js/next-boot.js"></script><script src="/js/pjax.js"></script>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/hexo-generator-searchdb/1.4.1/search.js" integrity="sha256-1kfA5uHPf65M5cphT2dvymhkuyHPQp5A53EGZOnOLmc=" crossorigin="anonymous"></script>
<script src="/js/third-party/search/local-search.js"></script>




  <script src="/js/third-party/fancybox.js"></script>

  <script src="/js/third-party/pace.js"></script>


  




  

  <script class="next-config" data-name="enableMath" type="application/json">true</script><script class="next-config" data-name="mathjax" type="application/json">{"enable":true,"tags":"none","js":{"url":"https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.2.2/es5/tex-mml-chtml.js","integrity":"sha256-MASABpB4tYktI2Oitl4t+78w/lyA+D7b/s9GEP0JOGI="}}</script>
<script src="/js/third-party/math/mathjax.js"></script>


 
        <div id="click-show-text"
            data-mobile = false
            data-text = 富强,民主,文明,和谐,自由,平等,公正,法制,爱国,敬业,诚信,友善
            data-fontsize = 15px
            data-random= false>
        </div>
       

      
        <script async src=https://cdn.jsdelivr.net/npm/hexo-next-mouse-effect@latest/click/showText.js></script>
      

      
    




    <script async src="/js/fancybox_param.js"></script>





<!-- APlayer本体 -->



</body>
</html>
